Commit 14f7b782 authored by haukda60920's avatar haukda60920
Browse files

init

parent 155422c0
package com.example.hbox
import androidx.test.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getTargetContext()
assertEquals("com.example.hbox", appContext.packageName)
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.hbox">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:usesCleartextTraffic="true"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".control.SettingsActivity"
android:label="@string/title_activity_settings">
</activity>
adb<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
\ No newline at end of file
package com.example.hbox
import android.os.Bundle
import com.google.android.material.bottomnavigation.BottomNavigationView
import androidx.fragment.app.Fragment
import androidx.appcompat.app.AppCompatActivity
import android.util.Log
import com.example.hbox.control.ControlFragment
import com.example.hbox.history.HistoryFragment
import com.example.hbox.home.HomeFragment
import com.example.hbox.settings.SettingsFragment
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
private lateinit var homeFragment : HomeFragment
private lateinit var controlFragment : ControlFragment
private lateinit var historyFragment : HistoryFragment
private lateinit var settingsFragment : SettingsFragment
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d("d", "onCreate von MainActivity")
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
homeFragment = HomeFragment()
controlFragment = ControlFragment()
historyFragment = HistoryFragment()
settingsFragment = SettingsFragment()
replaceFragment(HomeFragment())
}
private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.navigation_home -> {
replaceFragment(homeFragment)
return@OnNavigationItemSelectedListener true
}
R.id.navigation_control-> {
replaceFragment(controlFragment)
return@OnNavigationItemSelectedListener true
}
R.id.navigation_history -> {
replaceFragment(historyFragment)
return@OnNavigationItemSelectedListener true
}
R.id.navigation_settings -> {
replaceFragment(settingsFragment)
return@OnNavigationItemSelectedListener true
}
}
false
}
private fun replaceFragment(fragment: Fragment) {
val fragmentTransition = supportFragmentManager.beginTransaction()
fragmentTransition.replace(R.id.FragmentContainer, fragment)
fragmentTransition.commit()
}
}
package com.example.hbox.control
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.example.hbox.R
class AutomaticFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, state: Bundle?): View? {
return inflater.inflate(R.layout.fragment_control_automatic, container, false)
}
}
package com.example.hbox.control
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.View.OnClickListener
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import com.example.hbox.R
/**
* The child fragment is no different than any other fragment other than it is now being maintained by
* a child FragmentManager.
*/
class ChildFragment : Fragment(), OnClickListener {
private var position: Int = 0
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, state: Bundle?): View? {
position = arguments?.getInt(POSITION_KEY) ?: 0
val root = inflater.inflate(R.layout.fragment_control_manually, container, false)
/*
(root?.findViewById(R.id.textViewPosition) as TextView).apply {
text = String.format("%s", position)
setOnClickListener(this@ChildFragment)
}
*/
return root
}
override fun onClick(v: View) {
Toast.makeText(v.context, "Clicked Position: $position", Toast.LENGTH_LONG).show()
}
companion object {
const val POSITION_KEY = "FragmentPositionKey"
fun newInstance(args: Bundle): ChildFragment = ChildFragment().apply { arguments = args }
}
}
package com.example.hbox.control
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
import androidx.viewpager.widget.ViewPager
import com.example.hbox.R
import com.google.android.material.tabs.TabLayout
class ControlFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_control, container, false)
val viewPager = view.findViewById<ViewPager>(R.id.viewPager)
viewPager.adapter = MyAdapter(childFragmentManager)
val tabStrip = view.findViewById<TabLayout>(R.id.pagerTabStrip)
tabStrip.setupWithViewPager(viewPager)
return view
}
class MyAdapter internal constructor(fm: FragmentManager) : FragmentPagerAdapter(fm) {
private var tabList: List<Fragment> = listOf(ManuallyFragment(), AutomaticFragment())
override fun getCount(): Int = tabList.size
override fun getItem(position: Int): Fragment = tabList[position]
override fun getPageTitle(position: Int): CharSequence {
return when (position) {
0 -> "Manuell"
else -> "Automatisch"
}
}
}
}
package com.example.hbox.control
import android.os.AsyncTask
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.example.hbox.R
import com.example.hbox.model.Device
import com.example.hbox.model.DeviceList
import com.google.gson.Gson
import com.history.ChartListViewAdapter
import java.net.HttpURLConnection
import java.net.URL
class ManuallyFragment : Fragment() {
/*
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, state: Bundle?): View? {
// fetch all available devices from server
val url = "http://87.156.139.113:3000/devices"
AsyncTaskHandleJson().execute(url)
// insert device switches in Layout
return inflater.inflate(R.layout.fragment_control_manually, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//create onClick listeners
}
inner class AsyncTaskHandleJson : AsyncTask<String, String, String>() {
override fun doInBackground(vararg url: String?): String {
var text: String
val connection = URL(url[0]).openConnection() as HttpURLConnection
try {
connection.connect()
text = connection.inputStream.use { it.reader().use { reader -> reader.readText() } }
} finally {
connection.disconnect()
}
return text
}
override fun onPostExecute(result: String?) {
super.onPostExecute(result)
handleJson(result)
}
}
private fun handleJson(jsonString: String?) {
val deviceList = ArrayList<Device>()
val devices = Gson().fromJson(jsonString, DeviceList::class.java)
devices.devices?.forEach { deviceList.add(it) }
if (activity == null) return
val adapter = ChartListViewAdapter(activity!!.applicationContext, sensorList)
//historyListView.adapter = adapter
}
*/
}
package com.example.hbox.control
import android.annotation.TargetApi
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.media.RingtoneManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.preference.ListPreference
import android.preference.Preference
import android.preference.PreferenceActivity
import android.preference.PreferenceFragment
import android.preference.PreferenceManager
import android.preference.RingtonePreference
import android.text.TextUtils
import android.view.MenuItem
import com.example.hbox.R
/**
* A [PreferenceActivity] that presents a set of application settings. On
* handset devices, settings are presented as a single list. On tablets,
* settings are split by category, with category headers shown to the left of
* the list of settings.
*
* See [Android Design: Settings](http://developer.android.com/design/patterns/settings.html)
* for design guidelines and the [Settings API Guide](http://developer.android.com/guide/topics/ui/settings.html)
* for more information on developing a Settings UI.
*/
/*
class SettingsActivity : AppCompatPreferenceActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setupActionBar()
}
/**
* Set up the [android.app.ActionBar], if the API is available.
*/
private fun setupActionBar() {
supportActionBar?.setDisplayHomeAsUpEnabled(true)
}
/**
* {@inheritDoc}
*/
override fun onIsMultiPane(): Boolean {
return isXLargeTablet(this)
}
/**
* {@inheritDoc}
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
override fun onBuildHeaders(target: List<PreferenceActivity.Header>) {
loadHeadersFromResource(R.xml.pref_headers, target)
}
/**
* This method stops fragment injection in malicious applications.
* Make sure to deny any unknown fragments here.
*/
override fun isValidFragment(fragmentName: String): Boolean {
return PreferenceFragment::class.java.name == fragmentName
|| GeneralPreferenceFragment::class.java.name == fragmentName
|| DataSyncPreferenceFragment::class.java.name == fragmentName
|| NotificationPreferenceFragment::class.java.name == fragmentName
}
/**
* This fragment shows general preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
class GeneralPreferenceFragment : PreferenceFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
addPreferencesFromResource(R.xml.pref_general)
setHasOptionsMenu(true)
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
bindPreferenceSummaryToValue(findPreference("example_text"))
bindPreferenceSummaryToValue(findPreference("example_list"))
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val id = item.itemId
if (id == android.R.id.home) {
startActivity(Intent(activity, SettingsActivity::class.java))
return true
}
return super.onOptionsItemSelected(item)
}
}
/**
* This fragment shows notification preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
class NotificationPreferenceFragment : PreferenceFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
addPreferencesFromResource(R.xml.pref_notification)
setHasOptionsMenu(true)
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"))
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val id = item.itemId
if (id == android.R.id.home) {
startActivity(Intent(activity, SettingsActivity::class.java))
return true
}
return super.onOptionsItemSelected(item)
}
}
/**
* This fragment shows data and sync preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
class DataSyncPreferenceFragment : PreferenceFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
addPreferencesFromResource(R.xml.pref_data_sync)
setHasOptionsMenu(true)
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
bindPreferenceSummaryToValue(findPreference("sync_frequency"))
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val id = item.itemId
if (id == android.R.id.home) {
startActivity(Intent(activity, SettingsActivity::class.java))
return true
}
return super.onOptionsItemSelected(item)
}
}
companion object {
/**
* A preference value change listener that updates the preference's summary
* to reflect its new value.
*/
private val sBindPreferenceSummaryToValueListener = Preference.OnPreferenceChangeListener { preference, value ->
val stringValue = value.toString()
if (preference is ListPreference) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list.
val listPreference = preference
val index = listPreference.findIndexOfValue(stringValue)
// Set the summary to reflect the new value.
preference.setSummary(
if (index >= 0)
listPreference.entries[index]
else
null
)
} else if (preference is RingtonePreference) {
// For ringtone preferences, look up the correct display value
// using RingtoneManager.
if (TextUtils.isEmpty(stringValue)) {
// Empty values correspond to 'silent' (no ringtone).
preference.setSummary(R.string.pref_ringtone_silent)
} else {
val ringtone = RingtoneManager.getRingtone(
preference.getContext(), Uri.parse(stringValue)
)
if (ringtone == null) {
// Clear the summary if there was a lookup error.
preference.setSummary(null)
} else {
// Set the summary to reflect the new ringtone display
// name.
val name = ringtone.getTitle(preference.getContext())
preference.setSummary(name)
}
}
} else {
// For all other preferences, set the summary to the value's
// simple string representation.
preference.summary = stringValue
}
true
}
/**
* Helper method to determine if the device has an extra-large screen. For
* example, 10" tablets are extra-large.
*/
private fun isXLargeTablet(context: Context): Boolean {
return context.resources.configuration.screenLayout and Configuration.SCREENLAYOUT_SIZE_MASK >= Configuration.SCREENLAYOUT_SIZE_XLARGE
}
/**
* Binds a preference's summary to its value. More specifically, when the
* preference's value is changed, its summary (line of text below the
* preference title) is updated to reflect the value. The summary is also
* immediately updated upon calling this method. The exact display format is
* dependent on the type of preference.
* @see .sBindPreferenceSummaryToValueListener
*/
private fun bindPreferenceSummaryToValue(preference: Preference) {
// Set the listener to watch for value changes.
preference.onPreferenceChangeListener = sBindPreferenceSummaryToValueListener
// Trigger the listener immediately with the preference's
// current value.
sBindPreferenceSummaryToValueListener.onPreferenceChange(
preference,
PreferenceManager
.getDefaultSharedPreferences(preference.context)
.getString(preference.key, "")
)
}
}
}
*/
package com.history
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import com.example.hbox.history.axisStyler.TemperatureAxisStyler
import com.example.hbox.history.dataSetStyler.TemperaturDataSetStyler
import com.example.hbox.history.limitLinesFormatter.WeekdayLimitLinesCreator
import com.github.mikephil.charting.charts.LineChart
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.data.LineDataSet
class ChartListViewAdapter(private val context: Context, private val sensorList: List<Sensor>) : BaseAdapter() {
override fun getItem(position: Int): Sensor = sensorList[position]
override fun getItemId(position: Int): Long = position.toLong()
override fun getCount(): Int = sensorList.size
@SuppressLint("ViewHolder")
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val chartView = LayoutInflater.from(context).inflate(com.example.hbox.R.layout.row_layout, parent, false)
val view = chartView.findViewById<LineChart>(com.example.hbox.R.id.chart)
// add entries
val entries: MutableList<Entry> = mutableListOf()
sensorList[position].data?.forEach {
entries.add(Entry(it.date.toFloat(), it.value))
}
// style dataset
val lineDataSet = LineDataSet(entries, sensorList[position].name)
TemperaturDataSetStyler.styleDataSet(lineDataSet)
// style axis
TemperatureAxisStyler.styleXAxis(view.xAxis)
TemperatureAxisStyler.styleYAxisLeft(view.axisLeft)
TemperatureAxisStyler.styleYAxisRight(view.axisRight)
// add weekdays
WeekdayLimitLinesCreator.create(view.xAxis, sensorList[position])
return view.apply {
data = LineData(lineDataSet)
isScaleYEnabled = false
description.isEnabled = false
setVisibleXRangeMinimum(86400000f)
setVisibleXRangeMaximum(86400000f*3)
moveViewToX(sensorList[position].data?.last()!!.date.toFloat().minus(86400000*3 ))
}
}
}
\ No newline at end of file