package com.example.meinwald.ui.area; import android.Manifest; import android.annotation.SuppressLint; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.pm.PackageManager; import android.database.DataSetObserver; import android.location.Location; import android.os.Bundle; import android.os.PowerManager; import android.preference.PreferenceManager; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.Button; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import com.example.meinwald.BuildConfig; import com.example.meinwald.R; import com.google.android.gms.location.FusedLocationProviderClient; import com.google.android.gms.location.LocationServices; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.Task; import com.google.android.material.floatingactionbutton.FloatingActionButton; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import static android.content.Context.POWER_SERVICE; public class AreaFragment extends Fragment { private static final String TAG = AreaFragment.class.getSimpleName(); /** * ______________________________________________________________________________________________ * AREA */ private OwnArea newArea = new OwnArea(); private List allAreas; private ListView areaList; private static final String KEY_AREA_REFERENCES = "areaReferences"; private List areaReferences; /** * ______________________________________________________________________________________________ * LOCATION */ private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1; /** * The geographical location where the device is currently located. * That is the last-known location retrieved by the Fused Location Provider. */ private Location mLastKnownLocation; /** * The entry point to the Fused Location Provider. */ private FusedLocationProviderClient mFusedLocationProviderClient; private boolean mLocationPermissionGranted; /** * The geographical locations which were received from location tracking. */ private List newPositions; /** * ______________________________________________________________________________________________ * CAMERA */ private static final int MY_CAMERA_PERMISSION_CODE = 100; private boolean mCameraPermissionGranted; private static final int CAMERA_REQUEST = 1888; /** * ______________________________________________________________________________________________ * STORAGE */ private static final int READ_EXTERNAL_STORAGE_CODE = 200; private static final int WRITE_EXTERNAL_STORAGE_CODE = 201; private boolean mReadStorageGranted; private boolean mWriteStorageGranted; PowerManager.WakeLock wakeLock; LocationService gps; @Override public void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); areaReferences = new ArrayList<>(); areaReferences = readAreaReferencesFromPreferences(); } @SuppressLint("InvalidWakeLockTag") public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = inflater.inflate(R.layout.fragment_areas, container, false); //construct a FusedLocationProviderClient. mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(getActivity()); //get permissions getLocationPermission(); getReadStoragePermission(); //instantiate area lists areaList = (ListView) root.findViewById(R.id.areaListView); allAreas = new ArrayList<>(); //get saved areas allAreas = loadAreasFromPreferences(); for (int i = 0; i < allAreas.size(); i++) { allAreas.get(i).setPathFile(areaReferences.get(i).getPath()); } instantiateAreasList(); PowerManager powerManager = (PowerManager) getContext().getSystemService(POWER_SERVICE); wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakelockTag"); gps = new LocationService(getContext()); //instantiate add button final FloatingActionButton fab = root.findViewById(R.id.fab_areas); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //permissions getLocationPermission(); getWriteStoragePPermission(); AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); newArea = new OwnArea(); newPositions = new ArrayList<>(); final View viewInflated = LayoutInflater.from(getContext()).inflate(R.layout.area_input, (ViewGroup) getView(), false); builder.setView(viewInflated); final Button startTracking = viewInflated.findViewById(R.id.areaStartTracking); final Button stopTracking = viewInflated.findViewById(R.id.areaStopTracking); final Button addLocation = viewInflated.findViewById(R.id.areaAddGPSPoint); startTracking.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //start tracking startLocationTracking(); startTracking.setVisibility(View.INVISIBLE); stopTracking.setVisibility(View.VISIBLE); addLocation.setVisibility(View.INVISIBLE); } }); stopTracking.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //stop tracking List positionsToAdd = new ArrayList<>(); positionsToAdd = gps.getPositions(); for (LatLng pos: positionsToAdd) { newPositions.add(pos); } if (BuildConfig.DEBUG) { Log.d(TAG, "Received locations: " + newPositions.size()); } wakeLock.release(); startTracking.setVisibility(View.VISIBLE); stopTracking.setVisibility(View.INVISIBLE); addLocation.setVisibility(View.VISIBLE); } }); addLocation.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //get last known location getDeviceLocation(); }}); builder.setPositiveButton("Bestätigen", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { final TextView titleView = viewInflated.findViewById(R.id.areaTitleUserInput); final TextView noticeView = viewInflated.findViewById(R.id.areaManagementNoticeUserInput); if (BuildConfig.DEBUG) { Log.d(TAG, "new title: " + titleView.getText()); } if (titleView.getText().length()>0) { //save user input newArea.setTitle(String.valueOf(titleView.getText())); newArea.setNotice(String.valueOf(noticeView.getText())); newArea.setLocations(newPositions); newArea.calculateArea(); boolean result = allAreas.add(newArea); if (BuildConfig.DEBUG) { Log.d(TAG, "new Task: " + newArea.toString()); Log.d(TAG, "add new task result: " + result); } newArea.writeToExternalStorage(getContext()); areaReferences.add(new AreaReference(newArea.getId(), newArea.getPathFile())); emptyPreferencesAndSaveAreaReferencesToPreferences(); //actuate list instantiateAreasList(); dialog.dismiss(); //confirm added task Toast toast = Toast.makeText(getActivity(), "Grundstück hinzugefügt!", Toast.LENGTH_SHORT); TextView v = (TextView) toast.getView().findViewById(android.R.id.message); if( v != null) { //text align center v.setGravity(Gravity.CENTER); } toast.show(); } else { //title needed Toast toast = Toast.makeText(getActivity(), "Grundstückstitel fehlt!", Toast.LENGTH_SHORT); TextView v = (TextView) toast.getView().findViewById(android.R.id.message); if( v != null) { //text align center v.setGravity(Gravity.CENTER); } toast.show(); } } }); builder.setNegativeButton("Abbrechen", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //reset variables newArea = new OwnArea(); newPositions = new ArrayList<>(); dialog.cancel(); } }); builder.show(); }}); return root; } /** * Get all stored areas and save them temporary. */ public void instantiateAreasList() { final AreaAdapter adapter = new AreaAdapter(getActivity().getApplicationContext(), allAreas); adapter.registerDataSetObserver(new DataSetObserver() { @Override public void onChanged() { super.onChanged(); if (BuildConfig.DEBUG) { Log.d(TAG, "onChanged"); } if (BuildConfig.DEBUG) { Log.d(TAG, "dataset size: " + areaList.getAdapter().getCount()); } if (areaList.getAdapter().getCount() > 0) { allAreas = new ArrayList<>(); areaReferences =new ArrayList<>(); for (int i = 0; i < areaList.getAdapter().getCount(); i++) { allAreas.add((OwnArea) areaList.getAdapter().getItem(i)); if (BuildConfig.DEBUG) { Log.d(TAG, "dataset added: " + allAreas.get(i).toString()); } areaReferences.add(new AreaReference(allAreas.get(i).getId(), allAreas.get(i).getPathFile())); } } } }); areaList.setAdapter(adapter); //initialise onClickListeners areaList.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView adapterView, View view, int i, long l) { //for (int j = 0; j < adapterView.getChildCount(); j++) //adapterView.getChildAt(j).setBackgroundColor(Color.TRANSPARENT); // change the background color of the selected element //view.setBackgroundColor(Color.LTGRAY); //adapterView.setSelection(i); }}); } @Override public void onPause() { super.onPause(); //save area references to shared preferences emptyPreferencesAndSaveAreaReferencesToPreferences(); } /** * Get OwnAreas from a JSONString. * @return */ private List loadAreasFromPreferences() { if (BuildConfig.DEBUG) { Log.d(TAG, "loadAreasFromPreferences() reference size: " + areaReferences.size()); } List areas = new ArrayList<>(); Integer i = 0; for (AreaReference reference: areaReferences) { String jsonString = readAreaFromExternalStorage(reference.getPath()); areas.add(new OwnArea(jsonString)); if (BuildConfig.DEBUG) { Log.d(TAG, "load area from preferences: " + areas.get(i).toString()); } i++; } return areas; } /** * Read OwnArea from file in external storage and return as a string. * * @param path File path where the OwnArea is saved. * @return */ private String readAreaFromExternalStorage(String path) { if (BuildConfig.DEBUG) { Log.d(TAG, "readAreaFromExternalStorage()"); } //Get the text file File file = new File(path); //Read text from file StringBuilder text = new StringBuilder(); try { BufferedReader br = new BufferedReader(new FileReader(file)); String line; while ((line = br.readLine()) != null) { text.append(line); if (BuildConfig.DEBUG) { Log.d(TAG, "Line: " + line); } } br.close(); } catch (IOException e) { if (BuildConfig.DEBUG) { Log.e(TAG, "Failed read from external storage: " + e.toString()); } } return text.toString(); } /** * Converts an OwnArea object into a JSONString object. * * @param area Area to convert into JSONString * @return */ public String areaToString(OwnArea area) { JSONObject areaObject = newArea.toJSONObject(); return areaObject.toString(); } /** * Reads areaReferences saved in preferences as jsonStrings * * @return list of AreaReferences */ private List readAreaReferencesFromPreferences() { if (BuildConfig.DEBUG) { Log.d(TAG, "readAreaReferencesFromPreferences()"); } List areas = new ArrayList<>(); try { String jsonString = PreferenceManager.getDefaultSharedPreferences(getContext()).getString(KEY_AREA_REFERENCES, "error"); if(!"error".equalsIgnoreCase(jsonString)) { JSONArray jsonObjects = new JSONArray(jsonString); for (int i = 0; i 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { mLocationPermissionGranted = true; } } case MY_CAMERA_PERMISSION_CODE: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { mCameraPermissionGranted = true; } } case READ_EXTERNAL_STORAGE_CODE: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { mReadStorageGranted = true; } } case WRITE_EXTERNAL_STORAGE_CODE: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { mWriteStorageGranted = true; } } } } public void getLocation(){ wakeLock.acquire(); gps = new LocationService(getContext()); } /** * Get the best and most recent location of the device, which may be null in rare * cases when a location is not available. * */ private void getDeviceLocation() { try { if (mLocationPermissionGranted) { Task locationResult = mFusedLocationProviderClient.getLastLocation(); locationResult.addOnCompleteListener(getActivity(), new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { // Set the last known position to the current location of the device and add to tracking stack mLastKnownLocation = task.getResult(); newPositions.add(new LatLng(mLastKnownLocation.getLatitude(),mLastKnownLocation.getLongitude())); if (BuildConfig.DEBUG) { if (task.getResult() != null) { Log.d(TAG, "getDeviceLocation: " + task.getResult().toString()); Log.d(TAG, "Size: " + newPositions.size()); } } } else { if (BuildConfig.DEBUG) { Log.d(TAG, "Current location is null. Using defaults."); Log.e(TAG, "Exception: %s", task.getException()); } } } }); } } catch (SecurityException e) { if (BuildConfig.DEBUG) { Log.e(TAG, "Exception occurred: "); e.printStackTrace(); } } } public void startLocationTracking(){ final Runnable runnable= new Runnable() { public void run() { // do stuff here getLocation(); } }; runnable.run(); } /** * Request location permission, so that we can get the location of the device. * The result of the permission request is handled by a callback, * onRequestPermissionsResult. * */ private void getLocationPermission() { if (ContextCompat.checkSelfPermission(getActivity().getApplicationContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { mLocationPermissionGranted = true; } else { ActivityCompat.requestPermissions(getActivity(), new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION); } } /** * Request read external storage permission, so that we can get saved images from external storage. * The result of the permission request is handled by a callback, * onRequestPermissionsResult. * */ private void getReadStoragePermission() { if (ContextCompat.checkSelfPermission(getActivity().getApplicationContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { mReadStorageGranted = true; } else { ActivityCompat.requestPermissions(getActivity(), new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE}, READ_EXTERNAL_STORAGE_CODE); } } /** * Request read external storage permission, so that we can get saved images from external storage. * The result of the permission request is handled by a callback, * onRequestPermissionsResult. * */ private void getWriteStoragePPermission() { if (ContextCompat.checkSelfPermission(getActivity().getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { mWriteStorageGranted = true; } else { ActivityCompat.requestPermissions(getActivity(), new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_CODE); } } }