|
|
@ -1,13 +1,14 @@ |
|
|
|
package co.zzyzx.sensorlogger |
|
|
|
package co.zzyzx.sensorlogger |
|
|
|
|
|
|
|
|
|
|
|
//import co.zzyzx.sensorlogger.db.RecordDatabase |
|
|
|
|
|
|
|
import android.Manifest |
|
|
|
import android.Manifest |
|
|
|
|
|
|
|
import android.app.ActivityManager |
|
|
|
import android.content.Context |
|
|
|
import android.content.Context |
|
|
|
import android.content.Intent |
|
|
|
import android.content.Intent |
|
|
|
import android.content.pm.PackageManager |
|
|
|
import android.content.pm.PackageManager |
|
|
|
import android.location.LocationManager |
|
|
|
import android.location.LocationManager |
|
|
|
import android.os.Build |
|
|
|
import android.os.Build |
|
|
|
import android.os.Bundle |
|
|
|
import android.os.Bundle |
|
|
|
|
|
|
|
import android.os.Environment |
|
|
|
import android.os.Handler |
|
|
|
import android.os.Handler |
|
|
|
import android.support.v4.app.ActivityCompat |
|
|
|
import android.support.v4.app.ActivityCompat |
|
|
|
import android.support.v4.content.ContextCompat |
|
|
|
import android.support.v4.content.ContextCompat |
|
|
@ -15,10 +16,17 @@ import android.support.v7.app.AppCompatActivity |
|
|
|
import android.view.View |
|
|
|
import android.view.View |
|
|
|
import android.widget.Toast |
|
|
|
import android.widget.Toast |
|
|
|
import co.zzyzx.sensorlogger.db.RecordRepository |
|
|
|
import co.zzyzx.sensorlogger.db.RecordRepository |
|
|
|
|
|
|
|
import com.opencsv.CSVWriter |
|
|
|
import kotlinx.android.synthetic.main.activity_main.* |
|
|
|
import kotlinx.android.synthetic.main.activity_main.* |
|
|
|
|
|
|
|
import kotlinx.coroutines.GlobalScope |
|
|
|
|
|
|
|
import kotlinx.coroutines.launch |
|
|
|
|
|
|
|
import java.io.File |
|
|
|
|
|
|
|
import java.io.FileWriter |
|
|
|
|
|
|
|
import java.time.Instant |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const val PERMISSION_LOCATION = 0 |
|
|
|
const val PERMISSION_LOCATION = 0 |
|
|
|
|
|
|
|
const val WRITE_EXTERNAL_STORAGE = 1 |
|
|
|
|
|
|
|
|
|
|
|
class MainActivity : AppCompatActivity(), |
|
|
|
class MainActivity : AppCompatActivity(), |
|
|
|
ActivityCompat.OnRequestPermissionsResultCallback { |
|
|
|
ActivityCompat.OnRequestPermissionsResultCallback { |
|
|
@ -60,8 +68,122 @@ class MainActivity : AppCompatActivity(), |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
reset_record_btn.let { |
|
|
|
|
|
|
|
it.setOnClickListener { |
|
|
|
|
|
|
|
recRepo.resetAllData() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export_record_btn.let { |
|
|
|
|
|
|
|
it.setOnClickListener { |
|
|
|
|
|
|
|
log("exporting something") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
actionOnService(Actions.STOP) |
|
|
|
|
|
|
|
if (ContextCompat.checkSelfPermission( |
|
|
|
|
|
|
|
applicationContext, |
|
|
|
|
|
|
|
Manifest.permission.WRITE_EXTERNAL_STORAGE |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
!= PackageManager.PERMISSION_GRANTED |
|
|
|
|
|
|
|
) { |
|
|
|
|
|
|
|
val perms = arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE) |
|
|
|
|
|
|
|
ActivityCompat.requestPermissions( |
|
|
|
|
|
|
|
this, perms, |
|
|
|
|
|
|
|
WRITE_EXTERNAL_STORAGE |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
GlobalScope.launch { |
|
|
|
|
|
|
|
exportToCSV() |
|
|
|
|
|
|
|
recRepo.resetAllData() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
updateCounter() |
|
|
|
updateCounter() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (isMyServiceRunning(EndlessService::class.java)) { |
|
|
|
|
|
|
|
start_service_btn.visibility = View.GONE |
|
|
|
|
|
|
|
stop_service_btn.visibility = View.VISIBLE |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
start_service_btn.visibility = View.VISIBLE |
|
|
|
|
|
|
|
stop_service_btn.visibility = View.GONE |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private fun exportToCSV() { |
|
|
|
|
|
|
|
val outputPath = |
|
|
|
|
|
|
|
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) |
|
|
|
|
|
|
|
var epochSec = Instant.now().epochSecond |
|
|
|
|
|
|
|
val acceleroFileName = "SensorLogger-${epochSec}-accelero.csv" |
|
|
|
|
|
|
|
val gyroFileName = "SensorLogger-${epochSec}-gyro.csv" |
|
|
|
|
|
|
|
var writerAccelero = CSVWriter(FileWriter("$outputPath${File.separator}$acceleroFileName")) |
|
|
|
|
|
|
|
var writerGyro = CSVWriter(FileWriter("$outputPath${File.separator}$gyroFileName")) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
writerAccelero.writeNext( |
|
|
|
|
|
|
|
arrayOf( |
|
|
|
|
|
|
|
"timestamp", |
|
|
|
|
|
|
|
"lat", |
|
|
|
|
|
|
|
"lon", |
|
|
|
|
|
|
|
"speed", |
|
|
|
|
|
|
|
"gps_timestamp", |
|
|
|
|
|
|
|
"accel-x", |
|
|
|
|
|
|
|
"accel-y", |
|
|
|
|
|
|
|
"accel-z" |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
writerGyro.writeNext( |
|
|
|
|
|
|
|
arrayOf( |
|
|
|
|
|
|
|
"timestamp", |
|
|
|
|
|
|
|
"lat", |
|
|
|
|
|
|
|
"lon", |
|
|
|
|
|
|
|
"speed", |
|
|
|
|
|
|
|
"gps_timestamp", |
|
|
|
|
|
|
|
"gyro-x", |
|
|
|
|
|
|
|
"gyro-y", |
|
|
|
|
|
|
|
"gyro-z" |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val records = recRepo.getAll() |
|
|
|
|
|
|
|
var lat = "" |
|
|
|
|
|
|
|
var lon = "" |
|
|
|
|
|
|
|
var speed = "" |
|
|
|
|
|
|
|
var time = "" |
|
|
|
|
|
|
|
for (rec in records) { |
|
|
|
|
|
|
|
if (rec.sensor == "location") { |
|
|
|
|
|
|
|
val one = rec.data?.split(",") as List<String> |
|
|
|
|
|
|
|
/* |
|
|
|
|
|
|
|
result.time, |
|
|
|
|
|
|
|
result.longitude.format(7), |
|
|
|
|
|
|
|
result.latitude.format(7), |
|
|
|
|
|
|
|
result.speed, |
|
|
|
|
|
|
|
result.altitude, |
|
|
|
|
|
|
|
result.bearing, |
|
|
|
|
|
|
|
result.accuracy, |
|
|
|
|
|
|
|
result.provider, |
|
|
|
|
|
|
|
result.isFromMockProvider |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
if (one.size != 0) { |
|
|
|
|
|
|
|
time = one[0] |
|
|
|
|
|
|
|
lon = one[1] |
|
|
|
|
|
|
|
lat = one[2] |
|
|
|
|
|
|
|
speed = one[3] |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else if (rec.sensor == "accelerometer") { |
|
|
|
|
|
|
|
val data = rec.data?.split(",") as List<String> |
|
|
|
|
|
|
|
val row = |
|
|
|
|
|
|
|
arrayOf("${rec.timestamp}", lat, lon, speed, time, data[0], data[1], data[2]) |
|
|
|
|
|
|
|
writerAccelero.writeNext(row) |
|
|
|
|
|
|
|
} else if (rec.sensor == "gyroscope") { |
|
|
|
|
|
|
|
val data = rec.data?.split(",") as List<String> |
|
|
|
|
|
|
|
val row = |
|
|
|
|
|
|
|
arrayOf("${rec.timestamp}", lat, lon, speed, time, data[0], data[1], data[2]) |
|
|
|
|
|
|
|
writerGyro.writeNext(row) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
writerAccelero.close() |
|
|
|
|
|
|
|
writerGyro.close() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private fun updateCounter() { |
|
|
|
private fun updateCounter() { |
|
|
@ -79,7 +201,6 @@ class MainActivity : AppCompatActivity(), |
|
|
|
reset_record_btn.visibility = View.VISIBLE |
|
|
|
reset_record_btn.visibility = View.VISIBLE |
|
|
|
export_record_btn.visibility = View.VISIBLE |
|
|
|
export_record_btn.visibility = View.VISIBLE |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
|
|
|
|
|
|
|
|
reset_record_btn.visibility = View.GONE |
|
|
|
reset_record_btn.visibility = View.GONE |
|
|
|
export_record_btn.visibility = View.GONE |
|
|
|
export_record_btn.visibility = View.GONE |
|
|
|
} |
|
|
|
} |
|
|
@ -91,8 +212,15 @@ class MainActivity : AppCompatActivity(), |
|
|
|
private fun UIStatusUpdates(hasLocPerm: Boolean = true) { |
|
|
|
private fun UIStatusUpdates(hasLocPerm: Boolean = true) { |
|
|
|
|
|
|
|
|
|
|
|
val mLocationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager |
|
|
|
val mLocationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager |
|
|
|
log("isLocationEnabled? ${mLocationManager.isLocationEnabled} - ${mLocationManager.allProviders}") |
|
|
|
val isLocationEnabled = ( |
|
|
|
if (hasLocPerm && mLocationManager.isLocationEnabled) { |
|
|
|
Build.VERSION.SDK_INT < Build.VERSION_CODES.P || ( |
|
|
|
|
|
|
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && |
|
|
|
|
|
|
|
mLocationManager.isLocationEnabled) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log("isLocationEnabled? $isLocationEnabled - ${mLocationManager.allProviders}") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (hasLocPerm && isLocationEnabled) { |
|
|
|
location_status_textview.text = "OK" |
|
|
|
location_status_textview.text = "OK" |
|
|
|
location_status_textview.setBackgroundColor( |
|
|
|
location_status_textview.setBackgroundColor( |
|
|
|
ContextCompat.getColor( |
|
|
|
ContextCompat.getColor( |
|
|
@ -113,11 +241,11 @@ class MainActivity : AppCompatActivity(), |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private fun requestForNecessaryPermissions() { |
|
|
|
private fun requestForNecessaryPermissions(perm: String = Manifest.permission.ACCESS_FINE_LOCATION) { |
|
|
|
// Here, thisActivity is the current activity |
|
|
|
// Here, thisActivity is the current activity |
|
|
|
if (ContextCompat.checkSelfPermission( |
|
|
|
if (ContextCompat.checkSelfPermission( |
|
|
|
this, |
|
|
|
this, |
|
|
|
Manifest.permission.ACCESS_FINE_LOCATION |
|
|
|
perm |
|
|
|
) |
|
|
|
) |
|
|
|
!= PackageManager.PERMISSION_GRANTED |
|
|
|
!= PackageManager.PERMISSION_GRANTED |
|
|
|
) { |
|
|
|
) { |
|
|
@ -125,14 +253,13 @@ class MainActivity : AppCompatActivity(), |
|
|
|
// Should we show an explanation? |
|
|
|
// Should we show an explanation? |
|
|
|
if (ActivityCompat.shouldShowRequestPermissionRationale( |
|
|
|
if (ActivityCompat.shouldShowRequestPermissionRationale( |
|
|
|
this, |
|
|
|
this, |
|
|
|
Manifest.permission.ACCESS_FINE_LOCATION |
|
|
|
perm |
|
|
|
) |
|
|
|
) |
|
|
|
) { |
|
|
|
) { |
|
|
|
val perms = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION) |
|
|
|
val perms = arrayOf(perm) |
|
|
|
ActivityCompat.requestPermissions( |
|
|
|
val permResult = |
|
|
|
this, perms, |
|
|
|
if (perm == Manifest.permission.ACCESS_FINE_LOCATION) PERMISSION_LOCATION else WRITE_EXTERNAL_STORAGE |
|
|
|
PERMISSION_LOCATION |
|
|
|
ActivityCompat.requestPermissions(this, perms, permResult) |
|
|
|
) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
UIStatusUpdates(false) |
|
|
|
UIStatusUpdates(false) |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -144,6 +271,16 @@ class MainActivity : AppCompatActivity(), |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private fun isMyServiceRunning(serviceClass: Class<*>): Boolean { |
|
|
|
|
|
|
|
val manager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager |
|
|
|
|
|
|
|
for (service in manager.getRunningServices(Integer.MAX_VALUE)) { |
|
|
|
|
|
|
|
if (serviceClass.name == service.service.className) { |
|
|
|
|
|
|
|
return true |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private fun actionOnService(action: Actions) { |
|
|
|
private fun actionOnService(action: Actions) { |
|
|
|
when (action) { |
|
|
|
when (action) { |
|
|
|
Actions.START -> { |
|
|
|
Actions.START -> { |
|
|
@ -185,6 +322,15 @@ class MainActivity : AppCompatActivity(), |
|
|
|
) |
|
|
|
) |
|
|
|
UIStatusUpdates(hasPerm) |
|
|
|
UIStatusUpdates(hasPerm) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
WRITE_EXTERNAL_STORAGE -> { |
|
|
|
|
|
|
|
val hasPerm = grantResult[0] == PackageManager.PERMISSION_GRANTED |
|
|
|
|
|
|
|
Toast.makeText( |
|
|
|
|
|
|
|
applicationContext, |
|
|
|
|
|
|
|
"${if (hasPerm) "Good" else "Bad"} Permission for storage", |
|
|
|
|
|
|
|
Toast.LENGTH_LONG |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
// UIStatusUpdates(hasPerm) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|