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.

AreaFragment.java 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. package com.example.meinwald.ui.area;
  2. import android.Manifest;
  3. import android.annotation.SuppressLint;
  4. import android.app.AlertDialog;
  5. import android.content.DialogInterface;
  6. import android.content.pm.PackageManager;
  7. import android.os.Bundle;
  8. import android.os.PowerManager;
  9. import android.preference.PreferenceManager;
  10. import android.util.Log;
  11. import android.view.Gravity;
  12. import android.view.LayoutInflater;
  13. import android.view.View;
  14. import android.view.ViewGroup;
  15. import android.widget.AdapterView;
  16. import android.widget.Button;
  17. import android.widget.ListView;
  18. import android.widget.TextView;
  19. import android.widget.Toast;
  20. import androidx.annotation.NonNull;
  21. import androidx.core.app.ActivityCompat;
  22. import androidx.core.content.ContextCompat;
  23. import androidx.fragment.app.Fragment;
  24. import com.example.meinwald.BuildConfig;
  25. import com.example.meinwald.R;
  26. import com.google.android.gms.location.FusedLocationProviderClient;
  27. import com.google.android.gms.location.LocationServices;
  28. import com.google.android.gms.maps.model.LatLng;
  29. import com.google.android.material.floatingactionbutton.FloatingActionButton;
  30. import org.json.JSONArray;
  31. import org.json.JSONException;
  32. import org.json.JSONObject;
  33. import java.io.BufferedReader;
  34. import java.io.File;
  35. import java.io.FileNotFoundException;
  36. import java.io.FileOutputStream;
  37. import java.io.FileReader;
  38. import java.io.IOException;
  39. import java.io.PrintWriter;
  40. import java.util.ArrayList;
  41. import java.util.List;
  42. import static android.content.Context.POWER_SERVICE;
  43. public class AreaFragment extends Fragment {
  44. private static final String TAG = AreaFragment.class.getSimpleName();
  45. /**
  46. * ______________________________________________________________________________________________
  47. * AREA
  48. */
  49. private OwnArea newArea = new OwnArea();
  50. private List<OwnArea> allAreas;
  51. private ListView areaList;
  52. private static final String KEY_AREA_REFERENCES = "areaReferences";
  53. private List<AreaReference> areaReferences;
  54. /**
  55. * ______________________________________________________________________________________________
  56. * LOCATION
  57. */
  58. private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
  59. /**
  60. * The entry point to the Fused Location Provider.
  61. */
  62. private FusedLocationProviderClient mFusedLocationProviderClient;
  63. private boolean mLocationPermissionGranted;
  64. /**
  65. * The geographical locations which were received from location tracking.
  66. */
  67. private List<LatLng> newPositions;
  68. /**
  69. * ______________________________________________________________________________________________
  70. * CAMERA
  71. */
  72. private static final int MY_CAMERA_PERMISSION_CODE = 100;
  73. private boolean mCameraPermissionGranted;
  74. private static final int CAMERA_REQUEST = 1888;
  75. /**
  76. * ______________________________________________________________________________________________
  77. * STORAGE
  78. */
  79. private static final int READ_EXTERNAL_STORAGE_CODE = 200;
  80. private static final int WRITE_EXTERNAL_STORAGE_CODE = 201;
  81. private boolean mReadStorageGranted;
  82. private boolean mWriteStorageGranted;
  83. PowerManager.WakeLock wakeLock;
  84. LocationService gps;
  85. @Override
  86. public void onCreate (Bundle savedInstanceState)
  87. {
  88. super.onCreate(savedInstanceState);
  89. areaReferences = new ArrayList<>();
  90. areaReferences = readAreaReferencesFromPreferences();
  91. }
  92. @SuppressLint("InvalidWakeLockTag")
  93. public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
  94. View root = inflater.inflate(R.layout.fragment_areas, container, false);
  95. //construct a FusedLocationProviderClient.
  96. mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(getActivity());
  97. //get permissions
  98. getLocationPermission();
  99. getReadStoragePermission();
  100. //instantiate area lists
  101. areaList = (ListView) root.findViewById(R.id.areaListView);
  102. allAreas = new ArrayList<>();
  103. //get saved areas
  104. allAreas = loadAreasFromPreferences();
  105. instantiateAreasList();
  106. PowerManager powerManager = (PowerManager) getContext().getSystemService(POWER_SERVICE);
  107. wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakelockTag");
  108. gps = new LocationService(getContext());
  109. //instantiate add button
  110. final FloatingActionButton fab = root.findViewById(R.id.fab_areas);
  111. fab.setOnClickListener(new View.OnClickListener() {
  112. @Override
  113. public void onClick(View view) {
  114. //permissions
  115. getLocationPermission();
  116. getWriteStoragePPermission();
  117. AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
  118. newArea = new OwnArea();
  119. final View viewInflated = LayoutInflater.from(getContext()).inflate(R.layout.area_input, (ViewGroup) getView(), false);
  120. builder.setView(viewInflated);
  121. final Button startTracking = viewInflated.findViewById(R.id.areaStartTracking);
  122. final Button stopTracking = viewInflated.findViewById(R.id.areaStopTracking);
  123. startTracking.setOnClickListener(new View.OnClickListener() {
  124. @Override
  125. public void onClick(View view) {
  126. //start tracking
  127. startLocationTracking();
  128. startTracking.setVisibility(View.INVISIBLE);
  129. stopTracking.setVisibility(View.VISIBLE);
  130. }
  131. });
  132. stopTracking.setOnClickListener(new View.OnClickListener() {
  133. @Override
  134. public void onClick(View view) {
  135. //stop tracking
  136. newPositions = gps.getPositions();
  137. if (BuildConfig.DEBUG)
  138. {
  139. Log.d(TAG, "Received locations: " + newPositions.size());
  140. }
  141. newArea.setLocations(newPositions);
  142. wakeLock.release();
  143. startTracking.setVisibility(View.VISIBLE);
  144. stopTracking.setVisibility(View.INVISIBLE);
  145. }
  146. });
  147. builder.setPositiveButton("Bestätigen", new DialogInterface.OnClickListener() {
  148. @Override
  149. public void onClick(DialogInterface dialog, int which) {
  150. final TextView titleView = viewInflated.findViewById(R.id.areaTitleUserInput);
  151. final TextView noticeView = viewInflated.findViewById(R.id.areaManagementNoticeUserInput);
  152. if (BuildConfig.DEBUG) {
  153. Log.d(TAG, "new title: " + titleView.getText());
  154. }
  155. if (titleView.getText().length()>0)
  156. {
  157. //save user input
  158. newArea.setTitle(String.valueOf(titleView.getText()));
  159. newArea.setNotice(String.valueOf(noticeView.getText()));
  160. boolean result = allAreas.add(newArea);
  161. if (BuildConfig.DEBUG)
  162. {
  163. Log.d(TAG, "new Task: " + newArea.toString());
  164. Log.d(TAG, "add new task result: " + result);
  165. }
  166. emptyPreferencesAndSaveAreaReferencesToPreferences();
  167. areaReferences.add(new AreaReference(newArea.getId(), writeAreaToExternalStorage(newArea)));
  168. //actuate list
  169. instantiateAreasList();
  170. dialog.dismiss();
  171. //confirm added task
  172. Toast toast = Toast.makeText(getActivity(), "Grundstück hinzugefügt!", Toast.LENGTH_SHORT);
  173. TextView v = (TextView) toast.getView().findViewById(android.R.id.message);
  174. if( v != null)
  175. {
  176. //text align center
  177. v.setGravity(Gravity.CENTER);
  178. }
  179. toast.show();
  180. }
  181. else
  182. {
  183. //title needed
  184. Toast toast = Toast.makeText(getActivity(), "Grundstückstitel fehlt!", Toast.LENGTH_SHORT);
  185. TextView v = (TextView) toast.getView().findViewById(android.R.id.message);
  186. if( v != null)
  187. {
  188. //text align center
  189. v.setGravity(Gravity.CENTER);
  190. }
  191. toast.show();
  192. }
  193. }
  194. });
  195. builder.setNegativeButton("Abbrechen", new DialogInterface.OnClickListener() {
  196. @Override
  197. public void onClick(DialogInterface dialog, int which) {
  198. dialog.cancel();
  199. }
  200. });
  201. builder.show();
  202. }});
  203. return root;
  204. }
  205. /**
  206. * Get all stored areas and save them temporary.
  207. */
  208. public void instantiateAreasList()
  209. {
  210. final AreaAdapter adapter = new AreaAdapter(getActivity().getApplicationContext(), allAreas);
  211. areaList.setAdapter(adapter);
  212. //initialise onClickListeners
  213. areaList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  214. @Override
  215. public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
  216. //for (int j = 0; j < adapterView.getChildCount(); j++)
  217. //adapterView.getChildAt(j).setBackgroundColor(Color.TRANSPARENT);
  218. // change the background color of the selected element
  219. //view.setBackgroundColor(Color.LTGRAY);
  220. //adapterView.setSelection(i);
  221. }});
  222. }
  223. @Override
  224. public void onPause() {
  225. super.onPause();
  226. //save area references to shared preferences
  227. emptyPreferencesAndSaveAreaReferencesToPreferences();
  228. }
  229. /**
  230. * Get OwnAreas from a JSONString.
  231. * @return
  232. */
  233. private List<OwnArea> loadAreasFromPreferences()
  234. {
  235. if (BuildConfig.DEBUG)
  236. {
  237. Log.d(TAG, "loadAreasFromPreferences() reference size: " + areaReferences.size());
  238. }
  239. List<OwnArea> areas = new ArrayList<>();
  240. Integer i = 0;
  241. for (AreaReference reference: areaReferences)
  242. {
  243. String jsonString = readAreaFromExternalStorage(reference.getPath());
  244. areas.add(new OwnArea(jsonString));
  245. if (BuildConfig.DEBUG)
  246. {
  247. Log.d(TAG, "load area from preferences: " + areas.get(i).toString());
  248. }
  249. i++;
  250. }
  251. return areas;
  252. }
  253. /**
  254. * Save OwnArea object in textfile on external storage.
  255. *
  256. * @param newArea OwnArea object to write to file.
  257. * @return
  258. */
  259. private String writeAreaToExternalStorage(OwnArea newArea){
  260. if (BuildConfig.DEBUG)
  261. {
  262. Log.d(TAG, "writeAreaToExternalStorage()");
  263. }
  264. // Find the root of the external storage.
  265. File root = android.os.Environment.getExternalStorageDirectory();
  266. //create file if it does not exist
  267. File path = new File (getContext().getFilesDir(), "meinWald" + File.pathSeparator + "areas");
  268. if(!path.exists()){
  269. path.mkdirs();
  270. if (BuildConfig.DEBUG)
  271. {
  272. Log.d(TAG, "Create new text file: " + path);
  273. }
  274. }
  275. File file = new File(path, newArea.getId() + ".txt");
  276. //open file and write to it
  277. try {
  278. FileOutputStream f = new FileOutputStream(file);
  279. PrintWriter pw = new PrintWriter(f);
  280. pw.print(areaToString(newArea));
  281. pw.close();
  282. f.close();
  283. } catch (FileNotFoundException e) {
  284. if (BuildConfig.DEBUG)
  285. {
  286. Log.e(TAG, "Failed write to external storage: " + e.toString());
  287. }
  288. } catch (IOException e) {
  289. if (BuildConfig.DEBUG)
  290. {
  291. Log.e(TAG, "Failed write to external storage: " + e.toString());
  292. }
  293. }
  294. return file.getPath();
  295. }
  296. /**
  297. * Read OwnArea from file in external storage and return as a string.
  298. *
  299. * @param path File path where the OwnArea is saved.
  300. * @return
  301. */
  302. private String readAreaFromExternalStorage(String path)
  303. {
  304. if (BuildConfig.DEBUG)
  305. {
  306. Log.d(TAG, "readAreaFromExternalStorage()");
  307. }
  308. //Get the text file
  309. File file = new File(path);
  310. //Read text from file
  311. StringBuilder text = new StringBuilder();
  312. try {
  313. BufferedReader br = new BufferedReader(new FileReader(file));
  314. String line;
  315. while ((line = br.readLine()) != null) {
  316. text.append(line);
  317. }
  318. br.close();
  319. }
  320. catch (IOException e) {
  321. if (BuildConfig.DEBUG)
  322. {
  323. Log.e(TAG, "Failed read from external storage: " + e.toString());
  324. }
  325. }
  326. return text.toString();
  327. }
  328. /**
  329. * Converts an OwnArea object into a JSONString object.
  330. *
  331. * @param area Area to convert into JSONString
  332. * @return
  333. */
  334. public String areaToString(OwnArea area)
  335. {
  336. JSONObject areaObject = newArea.toJSONObject();
  337. return areaObject.toString();
  338. }
  339. /**
  340. * Reads areaReferences saved in preferences as jsonStrings
  341. *
  342. * @return list of AreaReferences
  343. */
  344. private List<AreaReference> readAreaReferencesFromPreferences() {
  345. if (BuildConfig.DEBUG)
  346. {
  347. Log.d(TAG, "readAreaReferencesFromPreferences()");
  348. }
  349. List<AreaReference> areas = new ArrayList<>();
  350. try {
  351. String jsonString = PreferenceManager.getDefaultSharedPreferences(getContext()).getString(KEY_AREA_REFERENCES, "error");
  352. if(!"error".equalsIgnoreCase(jsonString)) {
  353. JSONArray jsonObjects = new JSONArray(jsonString);
  354. for (int i = 0; i<jsonObjects.length();i++) {
  355. areas.add(new AreaReference(jsonObjects.getJSONObject(i)));
  356. }
  357. }
  358. else
  359. {
  360. if (BuildConfig.DEBUG)
  361. {
  362. Log.e(TAG, "read area reference error");
  363. }
  364. }
  365. } catch (JSONException e) {
  366. if (BuildConfig.DEBUG) {
  367. Log.e(TAG, "Error while parsing area references as jsonObjects from preferences");
  368. e.printStackTrace();
  369. }
  370. }
  371. for (AreaReference reference: areas)
  372. {
  373. if (BuildConfig.DEBUG)
  374. {
  375. Log.d(TAG, "read reference: " + reference.toString());
  376. }
  377. }
  378. return areas;
  379. }
  380. /**
  381. * Saves epicolors to preferences
  382. */
  383. private void emptyPreferencesAndSaveAreaReferencesToPreferences()
  384. {
  385. if (BuildConfig.DEBUG)
  386. {
  387. Log.d(TAG, "emptyPreferencesAndSaveAreaReferencesToPreferences()");
  388. }
  389. if (!areaReferences.isEmpty()) {
  390. if (BuildConfig.DEBUG) {
  391. Log.d(TAG, "areaReferences not empty");
  392. }
  393. PreferenceManager.getDefaultSharedPreferences(getContext()).edit().remove(KEY_AREA_REFERENCES).commit();
  394. JSONArray writeObjects = new JSONArray();
  395. for (AreaReference reference: areaReferences) {
  396. JSONObject object = reference.toJSONObject();
  397. writeObjects.put(object);
  398. if (BuildConfig.DEBUG) {
  399. Log.d(TAG, "area reference is " + object.toString());
  400. }
  401. }
  402. PreferenceManager.getDefaultSharedPreferences(getContext()).edit().putString(KEY_AREA_REFERENCES, writeObjects.toString()).commit();
  403. }
  404. else
  405. {
  406. if (BuildConfig.DEBUG) {
  407. Log.e(TAG, "area references are empty!");
  408. }
  409. }
  410. }
  411. /**
  412. * DOCU ME!
  413. * TOOD: What are grant results etc for?
  414. * @param requestCode
  415. * @param permissions
  416. * @param grantResults
  417. */
  418. @Override
  419. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
  420. {
  421. if (BuildConfig.DEBUG) {
  422. Log.d(TAG, "onRequestPermissionResult Code: " + requestCode);
  423. }
  424. mLocationPermissionGranted = false;
  425. switch (requestCode) {
  426. case PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
  427. // If request is cancelled, the result arrays are empty.
  428. if (grantResults.length > 0
  429. && grantResults[0] == PackageManager.PERMISSION_GRANTED)
  430. {
  431. mLocationPermissionGranted = true;
  432. }
  433. }
  434. case MY_CAMERA_PERMISSION_CODE: {
  435. if (grantResults.length > 0
  436. && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
  437. mCameraPermissionGranted = true;
  438. }
  439. }
  440. case READ_EXTERNAL_STORAGE_CODE: {
  441. if (grantResults.length > 0
  442. && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
  443. mReadStorageGranted = true;
  444. }
  445. }
  446. case WRITE_EXTERNAL_STORAGE_CODE: {
  447. if (grantResults.length > 0
  448. && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
  449. mWriteStorageGranted = true;
  450. }
  451. }
  452. }
  453. }
  454. public void getLocation(){
  455. wakeLock.acquire();
  456. gps = new LocationService(getContext());
  457. }
  458. public void startLocationTracking(){
  459. final Runnable runnable= new Runnable() {
  460. public void run() {
  461. // do stuff here
  462. getLocation();
  463. }
  464. };
  465. runnable.run();
  466. }
  467. /**
  468. * Request location permission, so that we can get the location of the device.
  469. * The result of the permission request is handled by a callback,
  470. * onRequestPermissionsResult.
  471. *
  472. */
  473. private void getLocationPermission() {
  474. if (ContextCompat.checkSelfPermission(getActivity().getApplicationContext(),
  475. android.Manifest.permission.ACCESS_FINE_LOCATION)
  476. == PackageManager.PERMISSION_GRANTED) {
  477. mLocationPermissionGranted = true;
  478. } else {
  479. ActivityCompat.requestPermissions(getActivity(),
  480. new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
  481. PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
  482. }
  483. }
  484. /**
  485. * Request read external storage permission, so that we can get saved images from external storage.
  486. * The result of the permission request is handled by a callback,
  487. * onRequestPermissionsResult.
  488. *
  489. */
  490. private void getReadStoragePermission() {
  491. if (ContextCompat.checkSelfPermission(getActivity().getApplicationContext(),
  492. Manifest.permission.READ_EXTERNAL_STORAGE)
  493. == PackageManager.PERMISSION_GRANTED) {
  494. mReadStorageGranted = true;
  495. } else {
  496. ActivityCompat.requestPermissions(getActivity(),
  497. new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE},
  498. READ_EXTERNAL_STORAGE_CODE);
  499. }
  500. }
  501. /**
  502. * Request read external storage permission, so that we can get saved images from external storage.
  503. * The result of the permission request is handled by a callback,
  504. * onRequestPermissionsResult.
  505. *
  506. */
  507. private void getWriteStoragePPermission() {
  508. if (ContextCompat.checkSelfPermission(getActivity().getApplicationContext(),
  509. Manifest.permission.WRITE_EXTERNAL_STORAGE)
  510. == PackageManager.PERMISSION_GRANTED) {
  511. mWriteStorageGranted = true;
  512. } else {
  513. ActivityCompat.requestPermissions(getActivity(),
  514. new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE},
  515. WRITE_EXTERNAL_STORAGE_CODE);
  516. }
  517. }
  518. }