Projektarbeit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

EarthquakeMapsActivity.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. package de.edotzlaff.schockwelle;
  2. import android.Manifest;
  3. import android.content.Context;
  4. import android.content.pm.PackageManager;
  5. import android.location.Location;
  6. import android.net.wifi.WifiManager;
  7. import android.os.Bundle;
  8. import android.os.CountDownTimer;
  9. import android.os.SystemClock;
  10. import android.text.format.Formatter;
  11. import android.util.Log;
  12. import android.widget.Button;
  13. import android.widget.TextView;
  14. import android.widget.Toast;
  15. import android.hardware.Sensor;
  16. import android.hardware.SensorEvent;
  17. import android.hardware.SensorEventListener;
  18. import android.hardware.SensorManager;
  19. import androidx.annotation.NonNull;
  20. import androidx.core.app.ActivityCompat;
  21. import androidx.core.content.ContextCompat;
  22. import androidx.fragment.app.FragmentActivity;
  23. import com.google.android.gms.location.FusedLocationProviderClient;
  24. import com.google.android.gms.location.LocationServices;
  25. import com.google.android.gms.maps.CameraUpdateFactory;
  26. import com.google.android.gms.maps.GoogleMap;
  27. import com.google.android.gms.maps.OnMapReadyCallback;
  28. import com.google.android.gms.maps.SupportMapFragment;
  29. import com.google.android.gms.maps.model.LatLng;
  30. import com.google.android.gms.maps.model.MarkerOptions;
  31. import com.google.android.gms.tasks.OnCompleteListener;
  32. import com.google.android.gms.tasks.Task;
  33. import com.google.firebase.database.DataSnapshot;
  34. import com.google.firebase.database.DatabaseError;
  35. import com.google.firebase.database.DatabaseReference;
  36. import com.google.firebase.database.FirebaseDatabase;
  37. import com.google.firebase.database.ValueEventListener;
  38. import java.util.Calendar;
  39. import java.util.Date;
  40. import java.util.Objects;
  41. public class EarthquakeMapsActivity extends FragmentActivity implements OnMapReadyCallback {
  42. private static final String TAG = "MainActivity";
  43. private static final String FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION;
  44. private static final int LOCATION_PERMISSION_REQUEST_CODE = 1234;
  45. //vars
  46. private Boolean mLocationPermissionsGranted = false;
  47. private GoogleMap mMap;
  48. private FusedLocationProviderClient mFusedLocationProviderClient;
  49. private DatabaseReference mDatenbank;
  50. //Date currentTime; //Workaround für Crash: currentTime nicht als Datum sondern als Long zeitstempel
  51. Long currentTime;
  52. Location currentLocation;
  53. private double breitengrad;
  54. private double laengengrad;
  55. //Shake Sensor
  56. private SensorManager mSensorManager;
  57. private static final float mUpperThreshold = 1.5f; // für Emulator auf 1.5 setzen
  58. private static final float mLowerThreshold = 0.5f; // für Emulator auf 0.5 setzen
  59. private static final long mShakeDetectionLockTimeMicroSeconds = 10000;
  60. private float mAccel;
  61. private float mAccelCurrent;
  62. private float mAccelLast;
  63. private boolean mShakeDetectionIsActive = false;
  64. private boolean mShakeDetected = false;
  65. private CountDownTimer mLockTimer = new CountDownTimer(mShakeDetectionLockTimeMicroSeconds, 1000) {
  66. public void onTick(long millisUntilFinished) {
  67. ((TextView) findViewById(R.id.txtEarthquake)).setText("Earthquake started! Detection locked for " + millisUntilFinished / 1000 + " s");
  68. }
  69. public void onFinish() {
  70. mShakeDetectionIsActive = true;
  71. mShakeDetected = false;
  72. Toast.makeText(getApplicationContext(), "Shake Detection unlocked", Toast.LENGTH_SHORT).show();
  73. ( (TextView) findViewById(R.id.txtEarthquake)).setText("Shake your Smartphone for an Earthquake");
  74. }
  75. };
  76. @Override
  77. protected void onCreate(Bundle savedInstanceState) {
  78. super.onCreate(savedInstanceState);
  79. setContentView(R.layout.activity_earthquake_maps);
  80. TextView txtEarthquake = (TextView) findViewById(R.id.txtEarthquake);
  81. mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
  82. Objects.requireNonNull(mSensorManager).registerListener(mSensorListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
  83. mAccel = 1f;
  84. mAccelCurrent = SensorManager.GRAVITY_EARTH;
  85. mAccelLast = SensorManager.GRAVITY_EARTH;
  86. mShakeDetectionIsActive = true;
  87. mShakeDetected = false;
  88. getDataBaseValues(); //TODO Edward: Nur als Anmerkung, diese Methode erfolgt damit deine Methode getDeviceLocation rechtzeitig Koordinaten aus der DB bekommt
  89. //TODO Hast schon echt viel erledigt :D Ich habe gedacht das die Class EarthquakeMapsActivity Daten an die DB schickt und die SensorMapsActivity die Daten bekommt, ich glaub die Funktion muss in die andere Class
  90. getLocationPermission();
  91. }
  92. private final SensorEventListener mSensorListener = new SensorEventListener() {
  93. @Override
  94. public void onSensorChanged(SensorEvent event) {
  95. float x = event.values[0];
  96. float y = event.values[1];
  97. float z = event.values[2];
  98. mAccelLast = mAccelCurrent;
  99. mAccelCurrent = (float) Math.sqrt((double) (x * x + y * y + z * z));
  100. float delta = mAccelCurrent - mAccelLast;
  101. mAccel = mAccel * 0.9f + delta;
  102. // Log.d(TAG,"mAccel: "+ mAccel);
  103. if (mShakeDetectionIsActive) {
  104. if(Math.abs(mAccel) > mUpperThreshold) {
  105. new CountDownTimer(50, 10) {
  106. public void onTick(long millisUntilFinished) {
  107. if (Math.abs(mAccel) > mUpperThreshold) {
  108. mShakeDetectionIsActive = false;
  109. } else if (Math.abs(mAccel) < mLowerThreshold) {
  110. mShakeDetectionIsActive = true;
  111. this.cancel();
  112. }
  113. }
  114. public void onFinish() {
  115. if (Math.abs(mAccel) > mUpperThreshold) {
  116. mShakeDetectionIsActive = false;
  117. mShakeDetected = true;
  118. Toast.makeText(getApplicationContext(), "Shake event detected", Toast.LENGTH_SHORT).show();
  119. writeEarthquakeToDatabase();
  120. mLockTimer.start();
  121. } else {
  122. mShakeDetectionIsActive = true;
  123. mShakeDetected = false;
  124. }
  125. }
  126. }.start();
  127. }
  128. }
  129. }
  130. @Override
  131. public void onAccuracyChanged(Sensor sensor, int accuracy) {
  132. }
  133. };
  134. private void writeEarthquakeToDatabase()
  135. {
  136. setDataBaseValues(true);
  137. //TODO Erdbeben + Erzeugerparameter in Datenbank schreiben
  138. }
  139. @Override
  140. protected void onResume() {
  141. mSensorManager.registerListener(mSensorListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
  142. SensorManager.SENSOR_DELAY_NORMAL);
  143. super.onResume();
  144. }
  145. @Override
  146. protected void onPause() {
  147. mSensorManager.unregisterListener(mSensorListener);
  148. super.onPause();
  149. }
  150. private void getLocationPermission() {
  151. String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION};
  152. if (ContextCompat.checkSelfPermission(this.getApplicationContext(), FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
  153. mLocationPermissionsGranted = true;
  154. initMap();
  155. } else {
  156. ActivityCompat.requestPermissions(this, permissions, LOCATION_PERMISSION_REQUEST_CODE);
  157. }
  158. }
  159. @Override
  160. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  161. super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  162. mLocationPermissionsGranted = false;
  163. switch (requestCode) {
  164. case LOCATION_PERMISSION_REQUEST_CODE: {
  165. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
  166. mLocationPermissionsGranted = true;
  167. //initalize or map
  168. initMap();
  169. }
  170. }
  171. }
  172. }
  173. private void initMap() {
  174. SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
  175. mapFragment.getMapAsync(this);
  176. }
  177. @Override
  178. public void onMapReady(GoogleMap googleMap) {
  179. Toast.makeText(this, "Map is ready", Toast.LENGTH_SHORT).show();
  180. mMap = googleMap;
  181. if (mLocationPermissionsGranted) {
  182. getDeviceLocation();
  183. if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
  184. != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this,
  185. Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
  186. return;
  187. }
  188. mMap.setMyLocationEnabled(true);
  189. }
  190. // Add a marker in Sydney and move the camera
  191. //LatLng sydney = new LatLng(-34, 151);
  192. //mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
  193. //mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
  194. }
  195. private void getDeviceLocation(){
  196. mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
  197. try {
  198. if (mLocationPermissionsGranted){
  199. final Task location = mFusedLocationProviderClient.getLastLocation();
  200. location.addOnCompleteListener(new OnCompleteListener() {
  201. @Override
  202. public void onComplete(@NonNull Task task) {
  203. if (task.isSuccessful()){
  204. currentLocation = (Location) task.getResult();
  205. //currentTime = Calendar.getInstance().getTime(); //Workaround für Crash: currentTime nicht als Datum sondern als Long zeitstempel
  206. currentTime = Calendar.getInstance().getTimeInMillis();
  207. Toast.makeText(EarthquakeMapsActivity.this, currentTime.toString(), Toast.LENGTH_SHORT).show();
  208. currentLocation.setLatitude(breitengrad);
  209. currentLocation.setLongitude(laengengrad);
  210. setDataBaseValues(false); //TODO Edward: Die Funktion geht jetzt. Statt Datum wird Unix Zeitstempel als Long Typ verwendet
  211. moveCamera(new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude()),15f);
  212. }
  213. else{
  214. Toast.makeText(EarthquakeMapsActivity.this, "Current Location unavailable", Toast.LENGTH_SHORT).show();
  215. }
  216. }
  217. });
  218. }
  219. }catch (SecurityException e){
  220. Log.e(TAG,"Device Location not found" + e.getMessage());
  221. }
  222. }
  223. private void moveCamera(LatLng latlng, float zoom){
  224. Log.d(TAG,"Latitude: "+latlng.latitude+"Longitude: "+latlng.longitude);
  225. mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latlng, zoom));
  226. }
  227. public void getDataBaseValues()
  228. {
  229. mDatenbank = FirebaseDatabase.getInstance().getReference();
  230. mDatenbank.addValueEventListener(new ValueEventListener() {
  231. @Override
  232. public void onDataChange(@NonNull DataSnapshot snapshot) {
  233. processDataBaseValues(snapshot); //Daten Snapshot, Übergabe an processDataBaseValues
  234. }
  235. @Override
  236. public void onCancelled(@NonNull DatabaseError error) {
  237. getDataBaseFailure(error);
  238. }
  239. });
  240. }
  241. public void processDataBaseValues (DataSnapshot data)
  242. {
  243. //####### Hier wird beispielweise mit IDG1 gearbeitet, sollte aber klüger ausgearbeitet werden #######:
  244. String breitengradString = data.child("overview").child("IDG1").child("breitengrad").getValue().toString(); //TODO Aron/Team: Idee für passende ID je nach zugreifendem Gerät ==> Hardcoded oder flexibel?
  245. String laengengradString = data.child("overview").child("IDG1").child("laengengrad").getValue().toString();
  246. breitengrad = Double.parseDouble(breitengradString);
  247. laengengrad = Double.parseDouble(laengengradString);
  248. }
  249. public void getDataBaseFailure (DatabaseError error)
  250. {
  251. System.out.println("Fehler");
  252. Log.w("Datenbankfehler", error.toException());
  253. }
  254. //TODO Edward: Hier ist eine beispielhafte Methode mit der du Werte in der Datenbank setzen kannst
  255. public void setDataBaseValues(boolean vibration)
  256. {
  257. currentTime = Calendar.getInstance().getTimeInMillis();
  258. WifiManager wm = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
  259. int ip = wm.getConnectionInfo().getIpAddress();
  260. String ipAddress = String.format("%d.%d.%d.%d",(ip & 0xff),(ip >> 8 & 0xff),(ip >> 16 & 0xff), (ip >> 24 & 0xff));
  261. mDatenbank = FirebaseDatabase.getInstance().getReference();
  262. mDatenbank.child("overview").child("IDG1").child("ip").setValue(ipAddress);
  263. mDatenbank.child("overview").child("IDG1").child("vibration").setValue(vibration);
  264. mDatenbank.child("overview").child("IDG1").child("timestamp").setValue(currentTime); //aktueller Zeitstempel wird in Datenbank eingetragen
  265. mDatenbank.child("overview").child("IDG1").child("breitengrad").setValue(currentLocation.getLatitude()); //aktueller Breitengrad
  266. mDatenbank.child("overview").child("IDG1").child("laengengrad").setValue(currentLocation.getLongitude()); //aktueller Längergrad
  267. mDatenbank.child("overview").child("IDG1").child("amplitude").setValue(255);
  268. }
  269. }