Browse Source

initial area tracking

master
Felix Diemar 3 years ago
parent
commit
4153dbce6b
22 changed files with 2388 additions and 137 deletions
  1. 11
    0
      Code Android/meinWald/app/src/main/AndroidManifest.xml
  2. 10
    0
      Code Android/meinWald/app/src/main/java/com/example/meinwald/MainActivity.java
  3. 18
    0
      Code Android/meinWald/app/src/main/java/com/example/meinwald/MyApplication.java
  4. 143
    0
      Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/area/AreaAdapter.java
  5. 544
    13
      Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/area/AreaFragment.java
  6. 73
    0
      Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/area/AreaReference.java
  7. 0
    19
      Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/area/DashboardViewModel.java
  8. 290
    0
      Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/area/LocationService.java
  9. 170
    0
      Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/area/OwnArea.java
  10. 111
    0
      Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/map/MapsFragment.java
  11. 187
    0
      Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/task/OwnTask.java
  12. 147
    0
      Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/task/TaskAdapter.java
  13. 363
    71
      Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/task/TasksFragment.java
  14. 85
    0
      Code Android/meinWald/app/src/main/res/layout/area_element.xml
  15. 55
    0
      Code Android/meinWald/app/src/main/res/layout/area_input.xml
  16. 11
    11
      Code Android/meinWald/app/src/main/res/layout/fragment_areas.xml
  17. 15
    15
      Code Android/meinWald/app/src/main/res/layout/fragment_tasks.xml
  18. 23
    0
      Code Android/meinWald/app/src/main/res/layout/image_large.xml
  19. 85
    0
      Code Android/meinWald/app/src/main/res/layout/task_element.xml
  20. 33
    8
      Code Android/meinWald/app/src/main/res/layout/task_input.xml
  21. 1
    0
      Code Android/meinWald/app/src/main/res/values/colors.xml
  22. 13
    0
      Code Android/meinWald/app/src/main/res/values/styles.xml

+ 11
- 0
Code Android/meinWald/app/src/main/AndroidManifest.xml View File

@@ -3,6 +3,7 @@
package="com.example.meinwald">

<application
android:name="com.example.meinwald.MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
@@ -22,7 +23,17 @@
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />

<service
android:name=".ui.area.LocationTrack"
android:exported="false">
</service>

</application>

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

</manifest>

+ 10
- 0
Code Android/meinWald/app/src/main/java/com/example/meinwald/MainActivity.java View File

@@ -1,5 +1,6 @@
package com.example.meinwald;

import android.content.Context;
import android.os.Bundle;

import com.google.android.material.bottomnavigation.BottomNavigationView;
@@ -12,9 +13,14 @@ import androidx.navigation.ui.NavigationUI;

public class MainActivity extends AppCompatActivity {

private static Context context;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

context = getApplicationContext();

setContentView(R.layout.activity_main);
BottomNavigationView navView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
@@ -27,4 +33,8 @@ public class MainActivity extends AppCompatActivity {
NavigationUI.setupWithNavController(navView, navController);
}

public static Context getAppContext() {
return context;
}

}

+ 18
- 0
Code Android/meinWald/app/src/main/java/com/example/meinwald/MyApplication.java View File

@@ -0,0 +1,18 @@
package com.example.meinwald;

import android.app.Application;
import android.content.Context;

public class MyApplication extends Application {

private static Context context;

public void onCreate() {
super.onCreate();
MyApplication.context = getApplicationContext();
}

public static Context getAppContext() {
return MyApplication.context;
}
}

+ 143
- 0
Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/area/AreaAdapter.java View File

@@ -0,0 +1,143 @@
package com.example.meinwald.ui.area;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Rect;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.meinwald.BuildConfig;
import com.example.meinwald.R;
import com.example.meinwald.ui.task.OwnTask;
import com.google.android.material.floatingactionbutton.FloatingActionButton;

import java.util.ArrayList;
import java.util.List;

import androidx.appcompat.widget.AlertDialogLayout;
import androidx.appcompat.widget.LinearLayoutCompat;
import androidx.constraintlayout.widget.ConstraintLayout;

import static java.security.AccessController.getContext;

public class AreaAdapter extends BaseAdapter
{
List<OwnArea> areaList;
LayoutInflater inflater;
Context context;

public AreaAdapter(Context applicationContext, List<OwnArea> areaList)
{
this.areaList = new ArrayList<>();
this.areaList = areaList;
this.context = applicationContext;

inflater = LayoutInflater.from(applicationContext);

if (BuildConfig.DEBUG)
{
Log.d("AreaAdapter","size: " + areaList.size());
}
}

@Override
public View getView(final int i, View view, final ViewGroup viewGroup) {

view = inflater.inflate(R.layout.area_element, null);
final ConstraintLayout elementView = view.findViewById(R.id.areaInfoView);
final ConstraintLayout infovView = view.findViewById(R.id.areaInfoView);
final TextView title = (TextView) view.findViewById(R.id.areaInfoTitle);
final TextView notice = (TextView) view.findViewById(R.id.areaInfoNotice);
final ImageView icon = (ImageView) view.findViewById(R.id.areaIcon);
context = view.getContext();



if (BuildConfig.DEBUG)
{
Log.d("AreaAdapter",areaList.get(i).toString());
Log.d("AreaAdapter",areaList.get(i).getTitle());
Log.d("AreaAdapter",areaList.get(i).getNotice());
}

title.setText(areaList.get(i).getTitle());
notice.setText(areaList.get(i).getNotice());
icon.setImageBitmap(areaList.get(i).getImage());

title.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{


}
});

notice.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{


}
});

icon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{

final AlertDialog.Builder builder = new AlertDialog.Builder(v.getRootView().getContext());
final View viewInflated = LayoutInflater.from(v.getRootView().getContext()).inflate(R.layout.image_large, viewGroup, false);

builder.setView(viewInflated);

final ConstraintLayout imageViewLayout = viewInflated.findViewById(R.id.taskLargeImageLayout);
final ImageView imageView = viewInflated.findViewById(R.id.taskLargeImage);

imageView.setImageBitmap(areaList.get(i).getImage());

builder.setNegativeButton("Zurück", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});

builder.show();
}
});

view.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
// TODO Auto-generated method stub
return true;
}
});

return view;
}

@Override
public int getCount() {
return areaList.size();
}

@Override
public Object getItem(int i) {
return areaList.get(i);
}

@Override
public long getItemId(int i) {
return i;
}
}


+ 544
- 13
Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/area/AreaFragment.java View File

@@ -1,39 +1,570 @@
package com.example.meinwald.ui.area;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.os.IBinder;
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.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;

import com.example.meinwald.BuildConfig;
import com.example.meinwald.R;
import com.example.meinwald.ui.task.TaskAdapter;
import com.example.meinwald.ui.task.TasksFragment;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
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 org.json.JSONStringer;

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.InputStream;
import java.io.InputStreamReader;
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 DashboardViewModel dashboardViewModel;
private static final String TAG = TasksFragment.class.getSimpleName();

/**
* ______________________________________________________________________________________________
* AREA
*/
private OwnArea newArea = new OwnArea();
private List<OwnArea> allAreas;
private ListView areaList;
private static final String KEY_AREA_REFERENCES = "areaReferences";
private List<AreaReference> areaReferences;

/**
* ______________________________________________________________________________________________
* LOCATION
*/
private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
/**
* 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<LatLng> 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;


@SuppressLint("InvalidWakeLockTag")
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
dashboardViewModel =
ViewModelProviders.of(this).get(DashboardViewModel.class);
View root = inflater.inflate(R.layout.fragment_areas, container, false);
final TextView textView = root.findViewById(R.id.text_areas);
dashboardViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() {

//construct a FusedLocationProviderClient.
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(getActivity());

//get permissions
getLocationPermission();
getReadStoragePermission();

//instantiate area lists
areaList = (ListView) root.findViewById(R.id.areaListView);
allAreas = new ArrayList<>();
areaReferences = new ArrayList<>();

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 onChanged(@Nullable String s) {
textView.setText(s);
}
});
public void onClick(View view) {

//permissions
getLocationPermission();
getWriteStoragePPermission();

//get saved areas
areaReferences = readAreaReferencesFromPreferences();
allAreas = loadAreasFromPreferences();
instantiateAreasList();

AlertDialog.Builder builder = new AlertDialog.Builder(getContext());

newArea = new OwnArea();

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);


startTracking.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {

//start tracking
startLocationTracking();

startTracking.setVisibility(View.INVISIBLE);
stopTracking.setVisibility(View.VISIBLE);
}
});

stopTracking.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {

//stop tracking
newPositions = gps.getPositions();

if (BuildConfig.DEBUG)
{
Log.d(TAG, "Received locations: " + newPositions.size());
}

FloatingActionButton fab = root.findViewById(R.id.fab_areas);
newArea.setLocations(newPositions);
wakeLock.release();

startTracking.setVisibility(View.VISIBLE);
stopTracking.setVisibility(View.INVISIBLE);
}
});

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.areaNoticeUserInput);

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()));

boolean result = allAreas.add(newArea);

if (BuildConfig.DEBUG)
{
Log.d(TAG, "new Task: " + newArea.toString());
Log.d(TAG, "add new task result: " + result);
}

//stop tracking
//wakeLock.release();

//save new area
allAreas.add(newArea);
writeAreaToExternalStorage(newArea);

//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) {
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);
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() {

//save area references to shared preferences
emptyPreferencesAndSaveEpiColorsToPreferences();

super.onPause();
}

/**
* Get OwnAreas from a JSONString.
* @return
*/
private List<OwnArea> loadAreasFromPreferences()
{
List<OwnArea> areas = new ArrayList<>();

for (AreaReference reference: areaReferences)
{
String jsonString = readAreaFromExternalStorage(reference.getPath());

areas.add(new OwnArea(jsonString));
}

return areas;
}

/**
* Save OwnArea object in textfile on external storage.
*
* @param newArea OwnArea object to write to file.
* @return
*/
private String writeAreaToExternalStorage(OwnArea newArea){

// Find the root of the external storage.
File root = android.os.Environment.getExternalStorageDirectory();

//create file if it does not exist
File path = new File (root.getAbsolutePath() + "meinWald" + File.pathSeparator + "areas");
if(!path.exists()){
path.mkdirs();
}
File file = new File(path, newArea.getId() + ".txt");

//open file and write to it
try {
FileOutputStream f = new FileOutputStream(file);
PrintWriter pw = new PrintWriter(f);
pw.print(areaToString(newArea));
pw.close();
f.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

return file.getPath();
}

/**
* 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)
{
//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);
}
br.close();
}
catch (IOException e) {
e.printStackTrace();
}

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 epiColorDtos
*/
private List<AreaReference> readAreaReferencesFromPreferences() {
List<AreaReference> 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<jsonObjects.length();i++) {
areaReferences.add(new AreaReference(jsonObjects.getJSONObject(i)));
}
}
} catch (JSONException e) {
if (BuildConfig.DEBUG) {
Log.e(TAG, "Error while parsing epicolors as jsonObjects from preferences");
e.printStackTrace();
}
}

return areas;
}

/**
* Saves epicolors to preferences
*/
private void emptyPreferencesAndSaveEpiColorsToPreferences()
{
if (!areaReferences.isEmpty()) {
if (BuildConfig.DEBUG) {
Log.d(TAG, "areaReferences not empty");
}

PreferenceManager.getDefaultSharedPreferences(getContext()).edit().remove(KEY_AREA_REFERENCES).commit();

JSONArray writeObjects = new JSONArray();


for (AreaReference reference: areaReferences) {

JSONObject object = reference.toJSONObject();
writeObjects.put(object);

if (BuildConfig.DEBUG) {
Log.d("Color is ", object.toString());
}
}

PreferenceManager.getDefaultSharedPreferences(getContext()).edit().putString(KEY_AREA_REFERENCES, writeObjects.toString()).commit();
}
}

/**
* DOCU ME!
* TOOD: What are grant results etc for?
* @param requestCode
* @param permissions
* @param grantResults
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
{
if (BuildConfig.DEBUG) {
Log.d(TAG, "onRequestPermissionResult Code: " + requestCode);
}
mLocationPermissionGranted = false;
switch (requestCode) {
case PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 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());

}

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);
}
}
}

+ 73
- 0
Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/area/AreaReference.java View File

@@ -0,0 +1,73 @@
package com.example.meinwald.ui.area;

import android.util.Log;

import com.example.meinwald.BuildConfig;

import org.json.JSONException;
import org.json.JSONObject;

public class AreaReference
{
private String id;
private String path;

public AreaReference(String id, String path)
{
this.id = id;
this.path = path;
}

public String getId() {
return id;
}

public String getPath() {
return path;
}

/**
* Creates EpiColorDto from JSON-Representation
*
* @param jsonRepresentation epiColorDto values as jsonObject
*/
public AreaReference(JSONObject jsonRepresentation) {
try {
this.id = jsonRepresentation.getString("id");
this.path = jsonRepresentation.getString("path");
} catch (JSONException e) {
if (BuildConfig.DEBUG) {
Log.e(this.getClass().getSimpleName(),
String.format("Error while parsing epiColorDto to JSONObject. Values of epiColorDto: %s", this.toString()));
}
}
}

/**
* Returns AreaReference as JSONObject.
*
* @return the mapped object or null, if parsing fails
*/
public JSONObject toJSONObject() {
JSONObject object = new JSONObject();
try {
object.put("id",this.id);
object.put("path",this.path);
return object;
} catch (JSONException e) {
if (BuildConfig.DEBUG) {
Log.e(this.getClass().getSimpleName(),
String.format("Error while parsing epiColorDto to JSONObject. Values of epiColorDto: %s", this.toString()));
}
return null;
}
}

@Override
public String toString() {
return "AreaReference{" +
"id='" + id + '\'' +
", path='" + path + '\'' +
'}';
}
}

+ 0
- 19
Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/area/DashboardViewModel.java View File

@@ -1,19 +0,0 @@
package com.example.meinwald.ui.area;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class DashboardViewModel extends ViewModel {

private MutableLiveData<String> mText;

public DashboardViewModel() {
mText = new MutableLiveData<>();
mText.setValue("This is dashboard fragment");
}

public LiveData<String> getText() {
return mText;
}
}

+ 290
- 0
Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/area/LocationService.java View File

@@ -0,0 +1,290 @@
package com.example.meinwald.ui.area;


import android.Manifest;
import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.util.Log;

import com.example.meinwald.BuildConfig;
import com.google.android.gms.maps.model.LatLng;

import java.util.ArrayList;
import java.util.List;

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

//import static com.name.name.MapsActivity.NOTIFICATION_ID;

public class LocationService extends Service implements LocationListener {

private static final String TAG = "LocationService";

private final Context mContext;

// flag for GPS status
boolean isGPSEnabled = false;

// flag for network status
boolean isNetworkEnabled = false;

// flag for GPS status
boolean canGetLocation = false;
private boolean mLocationPermissionGranted;

Location location; // location
double latitude; // latitude
double longitude; // longitude

private List<LatLng> positions;

// The minimum distance to change Updates in meters
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 1; // 5 meters

// The minimum time between updates in milliseconds
private static final long MIN_TIME_BW_UPDATES = 1000 * 5 * 1; // 5 seconds

// Declaring a Location Manager
protected LocationManager mLocationManager;

public LocationService(Context context) {

if (BuildConfig.DEBUG) {
Log.d(TAG, "LocationService(Context context)");
}

this.mContext = context;
this.positions = new ArrayList<>();
this.mLocationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);

getLocationPermission();

try {
// getting GPS status
isGPSEnabled = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

if (!isGPSEnabled && !isNetworkEnabled) {
// no network provider is enabled

Log.d(TAG,"No permission to get location from any provider!");

if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {


}

}
else
{
Log.d(TAG,"Permission to get location from any provider!");

this.canGetLocation = true;
// First get location from Network Provider
if (isNetworkEnabled) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

Log.d(TAG,"No permission to get location from network provider!");
}

if (BuildConfig.DEBUG)
{
Log.d(TAG, "getLocation() requestLocationUpdates() from GPS");
}

mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

if (mLocationManager != null) {
location = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

if (location != null) {
positions.add(new LatLng(location.getLatitude(), location.getLongitude()));
if (BuildConfig.DEBUG)
{
Log.d(TAG, "getLocation() new location added");
}
}
}
}

// if GPS Enabled get lat/long using GPS Services
if (isGPSEnabled && mLocationPermissionGranted) {
if (location == null) {
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

Log.d(TAG,"No permission to get location from gps provider!");
}

if (BuildConfig.DEBUG)
{
Log.d(TAG, "getLocation() requestLocationUpdates() from GPS");
}

mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

if (mLocationManager != null) {
location = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
positions.add(new LatLng(location.getLatitude(), location.getLongitude()));
if (BuildConfig.DEBUG)
{
Log.d(TAG, "getLocation() new location added");
}
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}

}

public void getLocation() {

if (BuildConfig.DEBUG) {
Log.d(TAG, "getLocation()");
}

}

/**
* Stop using GPS listener
* Calling this function will stop using GPS in your app
* */
public void stopUsingGPS(){
if(mLocationManager != null){
mLocationManager.removeUpdates(LocationService.this);
}
}

/**
* Function to get latitude
* */
public double getLatitude(){
if(location != null){
latitude = location.getLatitude();
}

// return latitude
return latitude;
}

public List<LatLng> getPositions()
{
if (BuildConfig.DEBUG)
{
Log.d(TAG, "getPositions() count: " + this.positions.size());
}

return this.positions;
}

/**
* Function to get longitude
* */
public double getLongitude(){
if(location != null){
longitude = location.getLongitude();
}

// return longitude
return longitude;
}

/**
* Function to check GPS/wifi enabled
* @return boolean
* */
public boolean canGetLocation() {
return this.canGetLocation;
}

/**
* Function to show settings alert dialog
* On pressing Settings button will lauch Settings Options
* */
public void showSettingsAlert(){
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);

// Setting Dialog Title
alertDialog.setTitle("GPS is settings");

// Setting Dialog Message
alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");

// On pressing Settings button
alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int which) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
}
});

// on pressing cancel button
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});

// Showing Alert Message
alertDialog.show();
}

/**
* 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(mContext,
android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
}
else
{
mLocationPermissionGranted = false;
}
}

@Override
public void onLocationChanged(Location location) {
if (BuildConfig.DEBUG)
{
Log.d(TAG, "onLocationChanged(), new location: " + location.toString());
}

positions.add(new LatLng(location.getLatitude(), getLongitude()));
}

@Override
public void onProviderDisabled(String provider) {
}

@Override
public void onProviderEnabled(String provider) {
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}

@Override
public IBinder onBind(Intent arg0) {
return null;
}
}

+ 170
- 0
Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/area/OwnArea.java View File

@@ -0,0 +1,170 @@
package com.example.meinwald.ui.area;

import android.graphics.Bitmap;
import android.location.Location;
import android.util.Log;

import com.example.meinwald.BuildConfig;
import com.google.android.gms.maps.model.LatLng;

import org.json.JSONException;
import org.json.JSONObject;

import java.sql.Time;
import java.util.Date;
import java.util.List;

public class OwnArea {

private String title;
private String notice;
private List<LatLng> locations;
private Bitmap image;
private String pathImage;
private String pathLocations;
private String id;
private Date time;

public void setImage(Bitmap image) {
this.image = image;
}

public void setTitle(String title) {
this.title = title;
this.id = generateAreaID(title);
}

public void setNotice(String notice) {
this.notice = notice;
}

public void setLocations(List<LatLng> locations) {
this.locations = locations;
}

public void setPathImage(String pathImage) {
this.pathImage = pathImage;
}

public void setPathLocations(String pathLocations) {
this.pathLocations = pathLocations;
}

public String getNotice() {
return notice;
}

public String getTitle() {
return title;
}

public Bitmap getImage() {
return image;
}

public List<LatLng> getLocations() {
return locations;
}

public String getId() {
return id;
}

public String getPathImage() {
return pathImage;
}

public String getPathLocations() {
return pathLocations;
}

public OwnArea()
{

}

public OwnArea(String jsonString){
try {
JSONObject areaObject = new JSONObject(jsonString);
this.title = areaObject.getString("title");
this.notice = areaObject.getString("description");
this.id = areaObject.getString("id");
this.time = new Date(areaObject.getString("time"));

} catch (JSONException e) {
if (BuildConfig.DEBUG) {
Log.e(this.getClass().getSimpleName(), "earthquakeJSON " + jsonString);
e.printStackTrace();
}
}
}

private String generateAreaID(String title)
{
String id = title.replaceAll(" ", "_") + "_" + new Date().getTime();

if (BuildConfig.DEBUG)
{
Log.d(getClass().getSimpleName(), "new ID: " + id);
}
return id;
}


/**
* Returns OwnArea as JSONObject.
*
* @return the mapped object or null, if parsing fails
*/
public JSONObject toJSONObject() {
JSONObject object = new JSONObject();
try {
object.put("title",this.title);
object.put("description",this.notice);
object.put("id",this.id);

if (this.time != null)
{
object.put("time", this.time);
}
else
{
object.put("time", new Date().getTime());
}


JSONObject locations = new JSONObject();
Long count = Long.valueOf(0);

//convert all locations
for (LatLng location: this.locations)
{
JSONObject locationObject = new JSONObject();
locationObject.put("Lat", location.latitude);
locationObject.put("Lng", location.longitude);
locations.put("location"+count, locationObject.toString());
}
object.put("locations", locations.toString());

return object;

} catch (JSONException e) {
if (BuildConfig.DEBUG) {
Log.e(this.getClass().getSimpleName(),
String.format("Error while parsing epiColorDto to JSONObject. Values of epiColorDto: %s", this.toString()));
}
return null;
}
}

@Override
public String toString() {
return "OwnArea{" +
"title='" + title + '\'' +
", notice='" + notice + '\'' +
", pathImage='" + pathImage + '\'' +
", pathLocations='" + pathLocations + '\'' +
", id='" + id + '\'' +
'}';
}
}

+ 111
- 0
Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/map/MapsFragment.java View File

@@ -1,27 +1,43 @@
package com.example.meinwald.ui.main.map;

import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.location.Location;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;

import com.example.meinwald.BuildConfig;
import com.example.meinwald.R;
import com.example.meinwald.ui.task.OwnTask;
import com.google.android.gms.dynamic.IObjectWrapper;
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.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptor;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;

import org.json.JSONArray;
import org.json.JSONException;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
@@ -62,6 +78,22 @@ public class MapsFragment extends Fragment implements OnMapReadyCallback {
*/
private Location mLastKnownLocation;

/**
* ______________________________________________________________________________________________
* TASKS
*/
private List<OwnTask> allTasks;
private static final String KEY_ALL_TASKS = "allTasks";

/**
* ______________________________________________________________________________________________
* STORAGEE
*/
private static final int READ_EXTERNAL_STORAGE_CODE = 200;
private static final int WRITE_EXTERNAL_STORAGE_CODE = 201;
private boolean mReadStorageGranted;
private boolean mWriteStorageGranted;

/**
* Is called when the MapsFragment view is created. Initializes all service connections, the location client and map itself.
* @param inflater Calling LayoutInflater
@@ -74,6 +106,12 @@ public class MapsFragment extends Fragment implements OnMapReadyCallback {
//get view to inflate
View root = inflater.inflate(fragment_map, container, false);

//get storage permission
getReadStoragePermission();

//get tasks
allTasks = readTasksFromPreferences();

//display map fragment
SupportMapFragment mapFragment = new SupportMapFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
@@ -187,6 +225,13 @@ public class MapsFragment extends Fragment implements OnMapReadyCallback {
mLocationPermissionGranted = true;
}
}
case READ_EXTERNAL_STORAGE_CODE: {

if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mReadStorageGranted = true;
}
}
}
}

@@ -274,6 +319,72 @@ public class MapsFragment extends Fragment implements OnMapReadyCallback {
e.printStackTrace();
}
}

for (OwnTask task: allTasks)
{
MarkerOptions marker = new MarkerOptions();

//set options
marker.position(new LatLng(task.getLocation().getLatitude(), task.getLocation().getLongitude()));
marker.title(task.getTitle());

mMap.addMarker(marker);
}
}

/**
* 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);
}
}

/**
* Reads tasks saved in preferences as jsonStrings
*
* @return list of OwnTask
*/
private List<OwnTask> readTasksFromPreferences() {
List<OwnTask> tasks = new ArrayList<>();

try {
String jsonString = PreferenceManager.getDefaultSharedPreferences(getContext()).getString(KEY_ALL_TASKS, "error");
if(!"error".equalsIgnoreCase(jsonString)) {
JSONArray jsonObjects = new JSONArray(jsonString);

for (int i = 0; i<jsonObjects.length();i++) {
tasks.add(new OwnTask(jsonObjects.getJSONObject(i)));

if (BuildConfig.DEBUG) {
Log.d(TAG, "Task loaded from shared preferences: " + tasks.get(i).toString());
}

Bitmap image = BitmapFactory.decodeFile(tasks.get(i).getPathImage() + File.separator + tasks.get(i).getId() + ".jpeg");
if (BuildConfig.DEBUG) {
Log.d(TAG, "Image loaded from shared preferences: " + image.getByteCount());
}
tasks.get(i).setImage(image);
}
}
} catch (JSONException e) {
if (BuildConfig.DEBUG) {
Log.e(TAG, "Error while parsing tasks as jsonObjects from preferences");
e.printStackTrace();
}
}

return tasks;
}

@Override

+ 187
- 0
Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/task/OwnTask.java View File

@@ -0,0 +1,187 @@
package com.example.meinwald.ui.task;

import android.graphics.Bitmap;
import android.location.Location;
import android.media.Image;
import android.util.Log;

import com.example.meinwald.BuildConfig;
import com.google.android.gms.maps.model.LatLng;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.Date;

public class OwnTask
{
private String title;
private String notice;
private Location location;
private Bitmap image;
private String pathImage;
private String id;

public OwnTask(String JSONString){
try {
JSONObject taskJSON = new JSONObject(JSONString);
this.title = taskJSON.getString("title");
this.notice = taskJSON.getString("notice");

this.location = new Location("");
this.location.setLatitude(taskJSON.getDouble("lat"));
this.location.setLongitude(taskJSON.getDouble("lng"));

this.pathImage = taskJSON.getString("pathImage");
this.id = taskJSON.getString("taskID");



} catch (JSONException e) {
if (BuildConfig.DEBUG) {
Log.e(this.getClass().getSimpleName(), "taskJSON: " + JSONString);
e.printStackTrace();
}
}
}

public OwnTask(JSONObject taskJSON){
try {
if (BuildConfig.DEBUG) {
Log.d(this.getClass().getSimpleName(), "JSONObject: " + taskJSON.toString());
}
this.title = taskJSON.getString("title");
this.notice = taskJSON.getString("notice");

this.location = new Location("");
this.location.setLatitude(taskJSON.getDouble("lat"));
this.location.setLongitude(taskJSON.getDouble("lng"));

this.id = taskJSON.getString("taskID");
this.pathImage = taskJSON.getString("taskPATHIMAGE");

} catch (JSONException e) {
if (BuildConfig.DEBUG) {
Log.e(this.getClass().getSimpleName(), "taskJSON: " + taskJSON.toString());
Log.e(this.getClass().getSimpleName(), "taskJSON Error: " + e.toString());
e.printStackTrace();
}
}
}

public OwnTask()
{
this.title = null;
this.notice = null;
this.location = null;
this.image = null;
this.pathImage = null;
this.id = null;
}

public OwnTask(String title, String notice, Location location, Bitmap image, String pathImage)
{
this.title = title;
this.notice = notice;
this.location = location;
this.image = image;
this.pathImage = pathImage;
this.id = generateTaskID(title);
}

public String getTitle() {
return title;
}

public String getNotice() {
return notice;
}

public Location getLocation() {
return location;
}

public Bitmap getImage() {
return image;
}

public String getPathImage() { return pathImage; }

public String getId() { return id; }

public void setTitle(String title)
{
this.id = generateTaskID(title);
this.title = title;
}

public void setNotice(String notice) {
this.notice = notice;
}

public void setLocation(Location location) {
this.location = location;
}

public void setImage(Bitmap image) {
this.image = image;
}

public void setPathImage(String pathImage) { this.pathImage = pathImage; }

@Override
public String toString() {
return "OwnTask{" +
"title='" + title + '\'' +
", notice='" + notice + '\'' +
", location=" + location + '\'' +
", pathImage=" + pathImage + '\'' +
", id=" + id +
'}';
}

private String generateTaskID(String title)
{
String id = title.replaceAll(" ", "_") + "_" + new Date().getTime();

if (BuildConfig.DEBUG)
{
Log.d(getClass().getSimpleName(), "new ID: " + id);
}
return id;
}

/**
* Returns task as JSONObject.
*
* @return the mapped object or null, if parsing fails
*/
public JSONObject toJSONObject() {
JSONObject object = new JSONObject();
try {
object.put("title",this.title);
object.put("notice",this.notice);
object.put("taskPATHIMAGE",this.pathImage);
object.put("taskID",this.id);
if (this.location != null)
{
object.put("lat",this.location.getLatitude());
object.put("lng",this.location.getLongitude());
}

if (BuildConfig.DEBUG) {
Log.d(this.getClass().getSimpleName(), "JSONObject: " + object.toString());
Log.d(this.getClass().getSimpleName(), "Task: " + this.toString());
Log.d(this.getClass().getSimpleName(), "path: " + this.getPathImage());
Log.d(this.getClass().getSimpleName(), "id: " + this.getId());
}
return object;
} catch (JSONException e) {
if (BuildConfig.DEBUG) {
Log.e(this.getClass().getSimpleName(), String.format("Error while parsing OwnTask to JSONObject. Values of OwnTask: %s", this.toString()));
}
return null;
}
}
}


+ 147
- 0
Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/task/TaskAdapter.java View File

@@ -0,0 +1,147 @@
package com.example.meinwald.ui.task;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Rect;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.meinwald.BuildConfig;
import com.example.meinwald.R;
import com.example.meinwald.ui.area.OwnArea;
import com.google.android.material.floatingactionbutton.FloatingActionButton;

import java.util.ArrayList;
import java.util.List;

import androidx.appcompat.widget.AlertDialogLayout;
import androidx.appcompat.widget.LinearLayoutCompat;
import androidx.constraintlayout.widget.ConstraintLayout;

import static java.security.AccessController.getContext;

public class TaskAdapter extends BaseAdapter
{
List<OwnTask> taskList;
LayoutInflater inflater;
Context context;

public TaskAdapter(Context applicationContext, List<OwnTask> taskList)
{
this.taskList = new ArrayList<>();
this.taskList = taskList;
this.context = applicationContext;

inflater = LayoutInflater.from(applicationContext);

if (BuildConfig.DEBUG)
{
//Log.d("TaskAdapter",taskList.get(0).toString());
Log.d("TaskAdapter","size: " + taskList.size());
}
}

@Override
public View getView(final int i, View view, final ViewGroup viewGroup) {

view = inflater.inflate(R.layout.task_element, null);
final ConstraintLayout elementView = view.findViewById(R.id.taskInfoView);
final ConstraintLayout infovView = view.findViewById(R.id.taskInfoView);
final TextView title = (TextView) view.findViewById(R.id.taskInfoTitle);
final TextView notice = (TextView) view.findViewById(R.id.taskInfoNotice);
final ImageView icon = (ImageView) view.findViewById(R.id.taskIcon);
context = view.getContext();



if (BuildConfig.DEBUG)
{
Log.d("TaskAdapter",taskList.get(i).toString());
Log.d("TaskAdapter",taskList.get(i).getTitle());
Log.d("TaskAdapter",taskList.get(i).getNotice());
}

title.setText(taskList.get(i).getTitle());
notice.setText(taskList.get(i).getNotice());
icon.setImageBitmap(taskList.get(i).getImage());

title.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{


}
});

notice.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{


}
});

icon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{

final AlertDialog.Builder builder = new AlertDialog.Builder(v.getRootView().getContext());
final View viewInflated = LayoutInflater.from(v.getRootView().getContext()).inflate(R.layout.image_large, viewGroup, false);

//viewInflated.setLayoutParams(new AlertDialogLayout.LayoutParams(taskList.get(i).getImage().getWidth(),5 * taskList.get(i).getImage().getHeight()));

builder.setView(viewInflated);

final ConstraintLayout imageViewLayout = viewInflated.findViewById(R.id.taskLargeImageLayout);
final ImageView imageView = viewInflated.findViewById(R.id.taskLargeImage);

//ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams(taskList.get(i).getImage().getWidth(),5 * taskList.get(i).getImage().getHeight());
//imageViewLayout.setLayoutParams(layoutParams);
imageView.setImageBitmap(taskList.get(i).getImage());

builder.setNegativeButton("Zurück", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});

builder.show();
}
});

view.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
// TODO Auto-generated method stub
return true;
}
});

return view;
}

@Override
public int getCount() {
return taskList.size();
}

@Override
public Object getItem(int i) {
return taskList.get(i);
}

@Override
public long getItemId(int i) {
return i;
}
}

+ 363
- 71
Code Android/meinWald/app/src/main/java/com/example/meinwald/ui/task/TasksFragment.java View File

@@ -1,23 +1,35 @@
package com.example.meinwald.ui.task;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.location.Location;
import android.media.Image;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
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.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
@@ -34,19 +46,32 @@ import com.google.android.gms.tasks.Task;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class TasksFragment extends Fragment {

private static final String TAG = TasksFragment.class.getSimpleName();

private View root;
private LayoutInflater layoutInflater;
private ImageView imageToAdd;
/**
* ______________________________________________________________________________________________
* LOCATION
*/
private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
private static final String KEY_LOCATION = "location";
/**
* The entry point to the Fused Location Provider.
*/
@@ -58,85 +83,51 @@ public class TasksFragment extends Fragment {
*/
private Location mLastKnownLocation;

private NotificationsViewModel notificationsViewModel;

public class OwnTask
{
private String title;
private String notice;
private Location location;
private Image image;

public OwnTask()
{
this.title = null;
this.notice = null;
this.location = null;
this.image = null;
}

public OwnTask(String title, String notice, Location location, Image image)
{
this.title = title;
this.notice = notice;
this.location = location;
this.image = image;
}

public String getTitle() {
return title;
}

public String getNotice() {
return notice;
}

public Location getLocation() {
return location;
}

public Image getImage() {
return image;
}

public void setTitle(String title) {
this.title = title;
}

public void setNotice(String notice) {
this.notice = notice;
}

public void setLocation(Location location) {
this.location = location;
}

public void setImage(Image image) {
this.image = image;
}
/**
* ______________________________________________________________________________________________
* TASKS
*/
private OwnTask newTask = new OwnTask();
private List<OwnTask> allTasks;
private ListView taskList;
private static final String KEY_ALL_TASKS = "allTasks";

@Override
public String toString() {
return "OwnTask{" +
"title='" + title + '\'' +
", notice='" + notice + '\'' +
", location=" + location +
'}';
}
}
/**
* ______________________________________________________________________________________________
* CAMERA
*/
private static final int MY_CAMERA_PERMISSION_CODE = 100;
private boolean mCameraPermissionGranted;
private static final int CAMERA_REQUEST = 1888;

OwnTask newTask = new OwnTask();
/**
* ______________________________________________________________________________________________
* 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;

public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

View root = inflater.inflate(R.layout.fragment_tasks, container, false);
layoutInflater = inflater;
root = inflater.inflate(R.layout.fragment_tasks, container, false);

taskList = (ListView) root.findViewById(R.id.taskListView);

//instance add button
//instantiate add button
FloatingActionButton fab = root.findViewById(R.id.fab_tasks);

allTasks = readTasksFromPreferences();
instantiateTaskList();

//construct a FusedLocationProviderClient.
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(getActivity());

//get read storage permission
getReadStoragePermission();

//get location permission
getLocationPermission();

@@ -145,11 +136,18 @@ public class TasksFragment extends Fragment {
public void onClick(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());

newTask = new OwnTask();

//check permissions
getDeviceLocation();
getCameraPPermission();
getWriteStoragePPermission();

final View viewInflated = LayoutInflater.from(getContext()).inflate(R.layout.task_input, (ViewGroup) getView(), false);
builder.setView(viewInflated);

imageToAdd = viewInflated.findViewById(R.id.taskImage);

//set location
final Button buttonSetLocation = viewInflated.findViewById(R.id.taskSetLocation);
final TextView locationText = viewInflated.findViewById(R.id.taskLocation);
@@ -157,6 +155,11 @@ public class TasksFragment extends Fragment {
buttonSetLocation.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {

if (BuildConfig.DEBUG)
{
Log.d(TAG, "add Location!");
}

getLocationPermission();
getDeviceLocation();

@@ -181,7 +184,29 @@ public class TasksFragment extends Fragment {

buttonAddPicture.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Code here executes on main thread after user presses button

if (BuildConfig.DEBUG)
{
Log.d(TAG, "add Picture!");
}

if (!mCameraPermissionGranted)
{
if (BuildConfig.DEBUG)
{
Log.d(TAG, "Camera permission not granted!");
}
getCameraPPermission();
}
else
{
if (BuildConfig.DEBUG)
{
Log.d(TAG, "Camera permission granted!");
}
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
}
}
});

@@ -192,17 +217,35 @@ public class TasksFragment extends Fragment {
final TextView titleView = viewInflated.findViewById(R.id.taskTitleUserInput);
final TextView noticeView = viewInflated.findViewById(R.id.taskNoticeUserInput);

if (titleView.getText()!=null)
if (BuildConfig.DEBUG) {
Log.d(TAG, "new title: " + titleView.getText());
}

if (titleView.getText().length()>0)
{
//save user input
newTask.setTitle(String.valueOf(titleView.getText()));
newTask.setNotice(String.valueOf(noticeView.getText()));


boolean result = allTasks.add(newTask);

if (BuildConfig.DEBUG)
{
Log.d(TAG, "new Task: " + newTask.toString());
Log.d(TAG, "add new task result: " + result);

/**
for (OwnTask task: allTasks)
{
if (BuildConfig.DEBUG) {
Log.d(TAG, task.toString());
}
}
**/
}

instantiateTaskList();
dialog.dismiss();

//confirm added task
@@ -244,6 +287,160 @@ public class TasksFragment extends Fragment {
return root;
}

@Override
public void onPause()
{
super.onPause();

emptyPreferencesAndSaveTasksToPreferences();
}

/**
* Saves tasks to preferences
*/
private void emptyPreferencesAndSaveTasksToPreferences() {
if (!allTasks.isEmpty()) {
if (BuildConfig.DEBUG) {
Log.d(TAG, "allTasks not empty!");
for (OwnTask task: allTasks)
{
Log.d(TAG, task.toString());
}
}

PreferenceManager.getDefaultSharedPreferences(getContext()).edit().remove(KEY_ALL_TASKS).commit();

JSONArray writeObjects = new JSONArray();

for (OwnTask task: allTasks)
{
if (BuildConfig.DEBUG) {
Log.d(TAG, task.toString());
}
}


for (OwnTask task: allTasks)
{
if (BuildConfig.DEBUG) {
Log.d(TAG, "save task: " + task.toString());
}

if (task.getImage() != null)
{

//save image to external storage and save path
String path = saveReceivedImage(task.getImage(), task.getId());
task.setPathImage(path);

if (BuildConfig.DEBUG) {
Log.d(TAG, "saved image with path: " + task.getPathImage());
}
}


JSONObject object = task.toJSONObject();
writeObjects.put(object);

if (BuildConfig.DEBUG) {
Log.d(TAG, object.toString());
}
}

PreferenceManager.getDefaultSharedPreferences(getContext()).edit().putString(KEY_ALL_TASKS, writeObjects.toString()).commit();
}
}

private String saveReceivedImage(Bitmap bitmap, String imageName){

File path = null;

try {
path = new File(getContext().getFilesDir(), "meinWald" + File.separator + "Images");
if(!path.exists()){
path.mkdirs();
}

if (BuildConfig.DEBUG) {
Log.d(TAG, "Image file path: " + path);
}

File outFile = new File(path, imageName + ".jpeg");
if (!outFile.exists())
{
FileOutputStream outputStream = new FileOutputStream(outFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
outputStream.close();
}

} catch (FileNotFoundException e) {
Log.e(TAG, "Saving received message failed with", e);
} catch (IOException e) {
Log.e(TAG, "Saving received message failed with", e);
}

return path.toString();
}

/**
* Reads tasks saved in preferences as jsonStrings
*
* @return list of OwnTask
*/
private List<OwnTask> readTasksFromPreferences() {
List<OwnTask> tasks = new ArrayList<>();

try {
String jsonString = PreferenceManager.getDefaultSharedPreferences(getContext()).getString(KEY_ALL_TASKS, "error");
if(!"error".equalsIgnoreCase(jsonString)) {
JSONArray jsonObjects = new JSONArray(jsonString);

for (int i = 0; i<jsonObjects.length();i++) {
tasks.add(new OwnTask(jsonObjects.getJSONObject(i)));

if (BuildConfig.DEBUG) {
Log.d(TAG, "Task loaded from shared preferences: " + tasks.get(i).toString());
}

Bitmap image = BitmapFactory.decodeFile(tasks.get(i).getPathImage() + File.separator + tasks.get(i).getId() + ".jpeg");
if (BuildConfig.DEBUG) {
Log.d(TAG, "Image loaded from shared preferences: " + image.getByteCount());
}
tasks.get(i).setImage(image);
}
}
} catch (JSONException e) {
if (BuildConfig.DEBUG) {
Log.e(TAG, "Error while parsing tasks as jsonObjects from preferences");
e.printStackTrace();
}
}

return tasks;
}

/**
* Get all stored tasks and save them temporary.
*/
public void instantiateTaskList()
{
final TaskAdapter adapter = new TaskAdapter(getActivity().getApplicationContext(),allTasks);
taskList.setAdapter(adapter);

//initialise onClickListeners
taskList.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);
}});
}

/**
* Request location permission, so that we can get the location of the device.
* The result of the permission request is handled by a callback,
@@ -262,6 +459,60 @@ public class TasksFragment extends Fragment {
}
}

/**
* Request camera permission, so that we can get an image from the camera.
* The result of the permission request is handled by a callback,
* onRequestPermissionsResult.
*
*/
private void getCameraPPermission() {
if (ContextCompat.checkSelfPermission(getActivity().getApplicationContext(),
Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED) {
mCameraPermissionGranted = true;
} else {
ActivityCompat.requestPermissions(getActivity(),
new String[]{android.Manifest.permission.CAMERA},
MY_CAMERA_PERMISSION_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 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);
}
}

/**
* DOCU ME!
* TOOD: What are grant results etc for?
@@ -272,6 +523,9 @@ public class TasksFragment extends Fragment {
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
{
if (BuildConfig.DEBUG) {
Log.d(TAG, "onRequestPermissionResult Code: " + requestCode);
}
mLocationPermissionGranted = false;
switch (requestCode) {
case PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
@@ -282,6 +536,44 @@ public class TasksFragment extends Fragment {
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;
}
}
}
}

@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK)
{
Bitmap photo = (Bitmap) data.getExtras().get("data");
newTask.setImage(photo);
newTask.setPathImage(saveReceivedImage(photo,newTask.getId()));

if (imageToAdd != null && photo != null)
{
imageToAdd.setImageBitmap(photo);
}
}
}


+ 85
- 0
Code Android/meinWald/app/src/main/res/layout/area_element.xml View File

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/areaElement"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:longClickable="true"
android:orientation="horizontal">

<TextView
android:id="@+id/areaInfoTitle"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_gravity="left"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:clickable="false"
android:focusable="false"

android:textColor="@android:color/primary_text_light"
android:textSize="22sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/areaInfoView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:orientation="horizontal"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/areaInfoTitle"
tools:visibility="visible">


<ImageView
android:id="@+id/areaIcon"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginBottom="5dp"
android:clickable="true"
android:focusable="false"
android:focusableInTouchMode="false"
android:src="@android:drawable/ic_menu_camera"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@android:drawable/ic_menu_camera" />

<TextView
android:id="@+id/areaInfoNotice"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:textColor="@android:color/primary_text_light"
android:textSize="12sp"
android:visibility="visible"
app:layout_constraintEnd_toStartOf="@+id/taskIcon"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

+ 55
- 0
Code Android/meinWald/app/src/main/res/layout/area_input.xml View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/layout_area_root"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="10dp" >

<TextView
android:id="@+id/areaTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Grundstück"
android:textAppearance="?android:attr/textAppearanceLarge" />

<EditText
android:id="@+id/areaTitleUserInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Titel eingeben!">

<requestFocus />

</EditText>

<TextView
android:id="@+id/areaNotice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Beschreibung"
android:textAppearance="?android:attr/textAppearanceLarge" />

<EditText
android:id="@+id/areaNoticeUserInput"
android:layout_width="match_parent"
android:layout_height="149dp"
android:hint="Beschreibung eingeben!"
android:isScrollContainer="true">
<requestFocus />
</EditText>

<Button
android:id="@+id/areaStartTracking"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Grundstücksaufnahme Starten!" />
<Button
android:id="@+id/areaStopTracking"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Grundstücksaufnahme Beenden!"
android:visibility="invisible"/>

</LinearLayout>

+ 11
- 11
Code Android/meinWald/app/src/main/res/layout/fragment_areas.xml View File

@@ -6,20 +6,20 @@
android:layout_height="match_parent"
tools:context=".ui.area.AreaFragment">

<TextView
android:id="@+id/text_areas"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:textSize="20sp"
<ListView
android:id="@+id/areaListView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="1dp"
android:layout_marginLeft="1dp"
android:layout_marginEnd="1dp"
android:layout_marginRight="1dp"
android:choiceMode="singleChoice"
android:listSelector="@color/selectionBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:gravity="center_horizontal" />
app:layout_constraintTop_toTopOf="parent" />

<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_areas"

+ 15
- 15
Code Android/meinWald/app/src/main/res/layout/fragment_tasks.xml View File

@@ -6,21 +6,6 @@
android:layout_height="match_parent"
tools:context=".ui.task.TasksFragment">

<TextView
android:id="@+id/text_tasks"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:layout_gravity="center_horizontal"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_tasks"
android:layout_width="wrap_content"
@@ -35,4 +20,19 @@
app:layout_constraintEnd_toEndOf="parent"
app:rippleColor="#00000000"
app:srcCompat="@android:drawable/ic_menu_add" />

<ListView
android:id="@+id/taskListView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="1dp"
android:layout_marginLeft="1dp"
android:layout_marginEnd="1dp"
android:layout_marginRight="1dp"
android:choiceMode="singleChoice"
android:listSelector="@color/selectionBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

+ 23
- 0
Code Android/meinWald/app/src/main/res/layout/image_large.xml View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/taskLargeImageLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintStart_toEndOf="parent"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:orientation="vertical">

<ImageView
android:id="@+id/taskLargeImage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

+ 85
- 0
Code Android/meinWald/app/src/main/res/layout/task_element.xml View File

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/taskElement"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:longClickable="true"
android:orientation="horizontal">

<TextView
android:id="@+id/taskInfoTitle"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_gravity="left"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:clickable="false"
android:focusable="false"

android:textColor="@android:color/primary_text_light"
android:textSize="22sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/taskInfoView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:orientation="horizontal"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/taskInfoTitle"
tools:visibility="visible">


<ImageView
android:id="@+id/taskIcon"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginBottom="5dp"
android:clickable="true"
android:focusable="false"
android:focusableInTouchMode="false"
android:src="@android:drawable/ic_menu_camera"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@android:drawable/ic_menu_camera" />

<TextView
android:id="@+id/taskInfoNotice"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:textColor="@android:color/primary_text_light"
android:textSize="12sp"
android:visibility="visible"
app:layout_constraintEnd_toStartOf="@+id/taskIcon"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

+ 33
- 8
Code Android/meinWald/app/src/main/res/layout/task_input.xml View File

@@ -61,13 +61,38 @@
android:layout_height="wrap_content"
android:text="Bild hinzufügen!" />

<ImageView
android:id="@+id/taskImage"
android:layout_width="243dp"
android:layout_height="149dp"
android:layout_gravity="center"
android:baselineAlignBottom="true"
android:foregroundGravity="center_vertical|center_horizontal"
app:srcCompat="@android:drawable/ic_menu_camera" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="309dp"
android:layout_marginStart="5dp"
android:layout_marginLeft="0dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:isScrollContainer="true"
android:orientation="horizontal"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/taskInfoTitle">

<ImageView
android:id="@+id/taskImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:baselineAlignBottom="true"
android:foregroundGravity="center_vertical|center_horizontal"
android:scaleType="fitXY"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@android:drawable/ic_menu_camera" />
</androidx.constraintlayout.widget.ConstraintLayout>

</LinearLayout>

+ 1
- 0
Code Android/meinWald/app/src/main/res/values/colors.xml View File

@@ -3,4 +3,5 @@
<color name="colorPrimary">#1B5E20</color>
<color name="colorPrimaryDark">#3700B3</color>
<color name="colorAccent">#03DAC5</color>
<color name="selectionBackground">#c0edc3</color>
</resources>

+ 13
- 0
Code Android/meinWald/app/src/main/res/values/styles.xml View File

@@ -7,4 +7,17 @@
<item name="colorAccent">@color/colorAccent</item>
</style>

<style name="ImageTheme" parent="android:Theme.Dialog">

<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">match_parent</item>
<item name="android:layout_marginTop">20dp</item>
<item name="android:layout_marginBottom">20dp</item>
<item name="android:layout_marginLeft">10dp</item>
<item name="android:layout_marginRight">10dp</item>
<!-- No backgrounds, titles or window float -->
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">false</item>
</style>

</resources>

Loading…
Cancel
Save