online lab

This commit is contained in:
Philipp Wo 2019-05-18 08:57:06 +02:00
parent e845195e9b
commit 4ff5b18998
14 changed files with 280 additions and 50 deletions

View File

@ -17,7 +17,8 @@
<option name="ALLOW_USER_CONFIGURATION" value="false" /> <option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" /> <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" /> <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" /> <option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res;file://$MODULE_DIR$/build/generated/res/resValues/debug" />
<option name="TEST_RES_FOLDERS_RELATIVE_PATH" value="" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" /> <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
</configuration> </configuration>
</facet> </facet>
@ -92,6 +93,7 @@
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundle_manifest" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundle_manifest" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/check_manifest_result" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/check_manifest_result" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/compatible_screen_manifest" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/compatible_screen_manifest" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/duplicate_classes_check" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" />
@ -102,24 +104,24 @@
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant_run_merged_manifests" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant_run_merged_manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant_run_split_apk_resources" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant_run_split_apk_resources" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javac" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/javac" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint_jar" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifest-checker" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifest-checker" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_assets" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_jni_libs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_manifests" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_shaders" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/metadata_feature_manifest" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/metadata_feature_manifest" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/prebuild" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/prebuild" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/processed_res" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/processed_res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/resources" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/resources" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shader_assets" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/shader_assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/signing_config" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/signing_config" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/split-apk" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/split-apk" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/tmp" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/validate_signing_config" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" /> <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" /> <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content> </content>
@ -141,18 +143,22 @@
<orderEntry type="library" name="Gradle: android.arch.lifecycle:runtime:1.1.1@aar" level="project" /> <orderEntry type="library" name="Gradle: android.arch.lifecycle:runtime:1.1.1@aar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-compat:28.0.0@aar" level="project" /> <orderEntry type="library" name="Gradle: com.android.support:support-compat:28.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:cardview-v7:28.0.0@aar" level="project" /> <orderEntry type="library" name="Gradle: com.android.support:cardview-v7:28.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-location:16.0.0@aar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: javax.inject:javax.inject:1@jar" level="project" /> <orderEntry type="library" scope="TEST" name="Gradle: javax.inject:javax.inject:1@jar" level="project" />
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-maps:16.1.0@aar" level="project" />
<orderEntry type="library" name="Gradle: android.arch.persistence:db-framework:1.1.1@aar" level="project" /> <orderEntry type="library" name="Gradle: android.arch.persistence:db-framework:1.1.1@aar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-vector-drawable:28.0.0@aar" level="project" /> <orderEntry type="library" name="Gradle: com.android.support:support-vector-drawable:28.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-core-utils:28.0.0@aar" level="project" /> <orderEntry type="library" name="Gradle: com.android.support:support-core-utils:28.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:recyclerview-v7:28.0.0@aar" level="project" /> <orderEntry type="library" name="Gradle: com.android.support:recyclerview-v7:28.0.0@aar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: com.android.support.test:monitor:1.0.2@aar" level="project" /> <orderEntry type="library" scope="TEST" name="Gradle: com.android.support.test:monitor:1.0.2@aar" level="project" />
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-places-placereport:16.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-annotations:28.0.0@jar" level="project" /> <orderEntry type="library" name="Gradle: com.android.support:support-annotations:28.0.0@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:interpolator:28.0.0@aar" level="project" /> <orderEntry type="library" name="Gradle: com.android.support:interpolator:28.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: android.arch.persistence.room:runtime:1.1.1@aar" level="project" /> <orderEntry type="library" name="Gradle: android.arch.persistence.room:runtime:1.1.1@aar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:transition:28.0.0@aar" level="project" /> <orderEntry type="library" name="Gradle: com.android.support:transition:28.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: android.arch.lifecycle:livedata:1.1.1@aar" level="project" /> <orderEntry type="library" name="Gradle: android.arch.lifecycle:livedata:1.1.1@aar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:drawerlayout:28.0.0@aar" level="project" /> <orderEntry type="library" name="Gradle: com.android.support:drawerlayout:28.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-v4:28.0.0@aar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: net.sf.kxml:kxml2:2.3.0@jar" level="project" /> <orderEntry type="library" scope="TEST" name="Gradle: net.sf.kxml:kxml2:2.3.0@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:documentfile:28.0.0@aar" level="project" /> <orderEntry type="library" name="Gradle: com.android.support:documentfile:28.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:slidingpanelayout:28.0.0@aar" level="project" /> <orderEntry type="library" name="Gradle: com.android.support:slidingpanelayout:28.0.0@aar" level="project" />
@ -165,15 +171,19 @@
<orderEntry type="library" scope="TEST" name="Gradle: com.google.code.findbugs:jsr305:2.0.1@jar" level="project" /> <orderEntry type="library" scope="TEST" name="Gradle: com.google.code.findbugs:jsr305:2.0.1@jar" level="project" />
<orderEntry type="library" name="Gradle: android.arch.core:common:1.1.1@jar" level="project" /> <orderEntry type="library" name="Gradle: android.arch.core:common:1.1.1@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:versionedparcelable:28.0.0@aar" level="project" /> <orderEntry type="library" name="Gradle: com.android.support:versionedparcelable:28.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-base:16.0.1@aar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: junit:junit:4.12@jar" level="project" /> <orderEntry type="library" scope="TEST" name="Gradle: junit:junit:4.12@jar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-core:1.3@jar" level="project" /> <orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-core:1.3@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:viewpager:28.0.0@aar" level="project" /> <orderEntry type="library" name="Gradle: com.android.support:viewpager:28.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: android.arch.persistence.room:common:1.1.1@jar" level="project" /> <orderEntry type="library" name="Gradle: android.arch.persistence.room:common:1.1.1@jar" level="project" />
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-basement:16.0.1@aar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-integration:1.3@jar" level="project" /> <orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-integration:1.3@jar" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-library:1.3@jar" level="project" /> <orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-library:1.3@jar" level="project" />
<orderEntry type="library" name="Gradle: android.arch.lifecycle:common:1.1.1@jar" level="project" /> <orderEntry type="library" name="Gradle: android.arch.lifecycle:common:1.1.1@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:coordinatorlayout:28.0.0@aar" level="project" /> <orderEntry type="library" name="Gradle: com.android.support:coordinatorlayout:28.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:customview:28.0.0@aar" level="project" /> <orderEntry type="library" name="Gradle: com.android.support:customview:28.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:swiperefreshlayout:28.0.0@aar" level="project" /> <orderEntry type="library" name="Gradle: com.android.support:swiperefreshlayout:28.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-media-compat:28.0.0@aar" level="project" />
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-tasks:16.0.1@aar" level="project" />
</component> </component>
</module> </module>

View File

@ -22,13 +22,18 @@ android {
} }
} }
dependencies { dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs') implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:support-media-compat:28.0.0'
implementation 'com.android.support:design:28.0.0' implementation 'com.android.support:design:28.0.0'
implementation 'com.android.support:support-v4:28.0.0'
implementation 'com.google.android.gms:play-services-maps:16.1.0'
implementation 'android.arch.persistence.room:runtime:1.1.1'
implementation 'com.google.android.gms:play-services-location:16.0.0'
annotationProcessor 'android.arch.persistence.room:compiler:1.1.1'
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'android.arch.persistence.room:runtime:1.1.1'
annotationProcessor 'android.arch.persistence.room:compiler:1.1.1'
} }

View File

@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
@ -24,6 +25,8 @@
</activity> </activity>
<meta-data android:name="com.google.android.geo.API_KEY" android:value="@string/google_maps_key"/>
<service android:name=".service.LocationService"/> <service android:name=".service.LocationService"/>
<activity android:name=".ui.activity.SplashActivity" <activity android:name=".ui.activity.SplashActivity"

View File

@ -7,21 +7,26 @@ import android.support.annotation.NonNull;
@Entity(tableName = "location") @Entity(tableName = "location")
public class Location { public class Location {
@PrimaryKey @PrimaryKey
@NonNull @NonNull
@ColumnInfo(name= "location") @ColumnInfo(name = "location")
private String location; private String location;
@ColumnInfo(name= "city") @ColumnInfo(name = "city")
private String city; private String city;
@ColumnInfo(name= "country") @ColumnInfo(name = "country")
private String country; private String country;
@ColumnInfo(name = "latitude")
private double latitude;
@ColumnInfo(name = "longitude")
private double longitude;
public Location(String location, String city, String country) { public Location(@NonNull String location, String city, String country, double latitude, double longitude) {
this.location = location; this.location = location;
this.city = city; this.city = city;
this.country = country; this.country = country;
this.latitude = latitude;
this.longitude = longitude;
} }
public String getLocation() { public String getLocation() {
@ -44,16 +49,29 @@ public class Location {
return country; return country;
} }
public void setCountry(String county) { public void setCountry(String country) {
this.country = county; this.country = country;
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
} }
@Override @Override
public String toString() { public String toString() {
return "Location{" + return location + ", " + city + ", " + country;
"location='" + location + '\'' +
", city='" + city + '\'' +
", county='" + country + '\'' +
'}';
} }
} }

View File

@ -1,15 +1,24 @@
package at.fhj.airkoality.service; package at.fhj.airkoality.service;
import android.Manifest;
import android.app.Notification; import android.app.Notification;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.Service; import android.app.Service;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.IBinder; import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.v4.app.ActivityCompat; import android.support.v4.app.ActivityCompat;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log; import android.util.Log;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import at.fhj.airkoality.AirKoalityApplication; import at.fhj.airkoality.AirKoalityApplication;
import at.fhj.airkoality.R; import at.fhj.airkoality.R;
import at.fhj.airkoality.ui.activity.MainActivity; import at.fhj.airkoality.ui.activity.MainActivity;
@ -20,6 +29,9 @@ public class LocationService extends Service {
private String TAG = "LocationService"; private String TAG = "LocationService";
private Notification notification; private Notification notification;
private FusedLocationProviderClient fsdpc;
private LocationCallback locationCallback;
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
@ -31,27 +43,64 @@ public class LocationService extends Service {
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "Service started"); Log.d(TAG, "Service started");
startForeground(1337,notification); startForeground(1337, notification);
startLocationUpdates();
return START_STICKY; return START_STICKY;
} }
@Override @Override
public void onCreate(){ public void onCreate() {
Log.d(TAG, "Service created");
super.onCreate(); super.onCreate();
setupNotification(); setupNotification();
Log.d(TAG, "Service created");
fsdpc = LocationServices.getFusedLocationProviderClient(this);
locationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult){
if(locationResult.getLocations().size()!=0){
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(LocationService.this);
preferences.edit()
.putFloat("latitude", (float) locationResult.getLocations().get(0).getLatitude())
.putFloat("longitude", (float) locationResult.getLocations().get(0).getLongitude()).apply();
}
}
};
}
}
@Override @Override
public void onDestroy(){ public void onDestroy() {
Log.d(TAG, "Service destroyed"); Log.d(TAG, "Service destroyed");
stopLocationUpdates();
super.onDestroy(); super.onDestroy();
} }
private void startLocationUpdates() {
LocationRequest request = new LocationRequest();
request.setInterval(5000);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
fsdpc.requestLocationUpdates(request, locationCallback, null);
}
}
private void stopLocationUpdates(){
fsdpc.removeLocationUpdates(locationCallback);
}
private void setupNotification() { private void setupNotification() {
Intent notificationIntent = new Intent(this, MainActivity.class); Intent notificationIntent = new Intent(this, MainActivity.class);

View File

@ -1,21 +1,22 @@
package at.fhj.airkoality.ui.activity; package at.fhj.airkoality.ui.activity;
import android.Manifest;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.design.widget.BottomNavigationView; import android.support.design.widget.BottomNavigationView;
import android.support.v4.app.Fragment; import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentTransaction; import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -23,6 +24,7 @@ import org.json.JSONObject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import at.fhj.airkoality.R; import at.fhj.airkoality.R;
import at.fhj.airkoality.db.room.AirKoalityDB; import at.fhj.airkoality.db.room.AirKoalityDB;
import at.fhj.airkoality.model.Location; import at.fhj.airkoality.model.Location;
@ -81,14 +83,14 @@ public class MainActivity extends AppCompatActivity implements RequestCallback {
setSelectedFragment(LOCATION_LIST); setSelectedFragment(LOCATION_LIST);
sharedPreferences.edit() sharedPreferences.edit()
.putString(FRAGMENT_PREF_KEY, LOCATION_LIST) .putString(FRAGMENT_PREF_KEY, LOCATION_LIST)
.commit(); .apply();
break; break;
case R.id.action_map: case R.id.action_map:
setSelectedFragment(MAP); setSelectedFragment(MAP);
sharedPreferences.edit() sharedPreferences.edit()
.putString(FRAGMENT_PREF_KEY, MAP) .putString(FRAGMENT_PREF_KEY, MAP)
.commit(); .apply();
break; break;
} }
return true; return true;
@ -100,9 +102,18 @@ public class MainActivity extends AppCompatActivity implements RequestCallback {
} }
private void fetchLocations(){ private void fetchLocations() {
HttpsGetTask httpsGetTask = new HttpsGetTask(this); HttpsGetTask httpsGetTask = new HttpsGetTask(this);
httpsGetTask.execute("https://api.openaq.org/v1/locations?country=AT&limit=200"); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
float latitude = preferences.getFloat("latitude", -1000);
float longitude = preferences.getFloat("longitude", -1000);
if (latitude == -1000 || longitude == -1000) {
httpsGetTask.execute("https://api.openaq.org/v1/locations?country=AT&limit=200");
} else {
httpsGetTask.execute("https://api.openaq.org/v1/locations?coordinates=" + latitude + "," + longitude + "&radius=" + 200000 + "&limit=10000");
}
} }
@ -168,6 +179,8 @@ public class MainActivity extends AppCompatActivity implements RequestCallback {
} }
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
@ -178,6 +191,9 @@ public class MainActivity extends AppCompatActivity implements RequestCallback {
case R.id.action_service_off: case R.id.action_service_off:
stopLocationService(); stopLocationService();
return true; return true;
case R.id.action_refresh:
fetchLocations();
return true;
default: default:
return false; return false;
} }
@ -185,11 +201,25 @@ public class MainActivity extends AppCompatActivity implements RequestCallback {
} }
private void startLocationService(){ private void startLocationService() {
Intent intent = new Intent(this, LocationService.class); if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
startService(intent); Intent intent = new Intent(this, LocationService.class);
startService(intent);
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 4711);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == 4711) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startLocationService();
}
}
}
}
private void stopLocationService(){ private void stopLocationService(){
@ -220,9 +250,20 @@ public class MainActivity extends AppCompatActivity implements RequestCallback {
String city = locationResult.getString("city"); String city = locationResult.getString("city");
String country = locationResult.getString("country"); String country = locationResult.getString("country");
Location location = new Location(locationName, city, country); JSONObject coordinates = locationResult.getJSONObject("coordinates");
double latitude = coordinates.getDouble("latitude");
double longitude = coordinates.getDouble("longitude");
Location location = new Location(locationName, city, country, latitude, longitude);
locations.add(location); locations.add(location);
} }
return locations; return locations;
} }
} }

View File

@ -1,28 +1,123 @@
package at.fhj.airkoality.ui.fragment; package at.fhj.airkoality.ui.fragment;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import at.fhj.airkoality.R; import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import java.util.List;
import at.fhj.airkoality.R;
import at.fhj.airkoality.db.room.AirKoalityDB;
import at.fhj.airkoality.model.Location;
import at.fhj.airkoality.ui.activity.MeasurementActivity;
public class MapFragment extends Fragment implements OnMapReadyCallback, GoogleMap.OnInfoWindowClickListener {
private MapView mapView;
private GoogleMap map;
private AirKoalityDB database;
public class MapFragment extends Fragment {
@Nullable @Nullable
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_map, container, false); View view = inflater.inflate(R.layout.fragment_map, container, false);
mapView = view.findViewById(R.id.map);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(this);
database = AirKoalityDB.getDatabase(getContext());
return view; return view;
} }
private void enableMyLocation() {
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if(map != null) {
map.setMyLocationEnabled(true);
}
}
}
public void refresh(){ public void refresh(){
addMapMarkers();
}
private void addMapMarkers() {
if(map != null) {
new Thread(() -> {
List<Location> locations = database.locationDAO().getAll();
getActivity().runOnUiThread(() -> {
map.clear();
for (Location location : locations) {
MarkerOptions markerOptions = new MarkerOptions()
.title(location.getLocation())
.snippet(location.getCity() + ", " + location.getCountry())
.position(new LatLng(location.getLatitude(), location.getLongitude()));
map.addMarker(markerOptions);
}
});
}).start();
}
}
@Override
public void onMapReady(GoogleMap googleMap) {
map = googleMap;
map.setOnInfoWindowClickListener(this);
enableMyLocation();
}
@Override
public void onInfoWindowClick(Marker marker) {
Intent intent = new Intent(getContext(), MeasurementActivity.class);
intent.putExtra("location_name", marker.getTitle());
startActivity(intent);
}
@Override
public void onResume() {
super.onResume();
mapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mapView.onPause();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
@Override
public void onDestroy() {
mapView.onDestroy();
super.onDestroy();
} }
} }

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#0019FD"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z"/>
</vector>

View File

@ -3,13 +3,10 @@
android:orientation="vertical" android:layout_width="match_parent" android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<TextView <com.google.android.gms.maps.MapView
android:layout_width="match_parent"
android:layout_width="match_parent" android:id="@+id/map"
android:layout_height="match_parent" android:layout_height="match_parent"></com.google.android.gms.maps.MapView>
android:gravity="center"
android:text="Map Fragment"
android:textSize="25dp"/>

View File

@ -6,6 +6,7 @@
<item android:id="@+id/action_service_on" app:showAsAction="always" android:title="Service on" android:icon="@drawable/ic_location_on"/> <item android:id="@+id/action_service_on" app:showAsAction="always" android:title="Service on" android:icon="@drawable/ic_location_on"/>
<item android:id="@+id/action_service_off" app:showAsAction="always" android:title="Service off" android:icon="@drawable/ic_location_off"/> <item android:id="@+id/action_service_off" app:showAsAction="always" android:title="Service off" android:icon="@drawable/ic_location_off"/>
<item android:id="@+id/action_refresh" app:showAsAction="always" android:title="refresh" android:icon="@drawable/ic_refresh_black_24dp"/>
</menu> </menu>

View File

@ -7,4 +7,5 @@
<string name="city_label">City:</string> <string name="city_label">City:</string>
<string name="country_label">Country:</string> <string name="country_label">Country:</string>
<string name="latest_measurements">Latest measurements:</string> <string name="latest_measurements">Latest measurements:</string>
<string name="google_maps_key">AIzaSyBQhcmDlyP01yNwTd4RTlatQIAJH3wJHw0</string>
</resources> </resources>

View File

@ -7,7 +7,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.3.1' classpath 'com.android.tools.build:gradle:3.4.1'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files

View File

@ -1,6 +1,6 @@
#Fri Mar 01 16:44:03 CET 2019 #Fri May 17 19:19:06 CEST 2019
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip

View File

@ -87,4 +87,9 @@ Service wird im Manifest deklariert
Um einen Foregroundservice zu starten muss das innerhalb von 5 Sekunden nach "start Service" (Intent) Um einen Foregroundservice zu starten muss das innerhalb von 5 Sekunden nach "start Service" (Intent)
Notifications benötigen immer einen Channel (ab Android O verfügbar) Notifications benötigen immer einen Channel und Channel ID (ab Android O verfügbar)
## 17.05.2019 - Online
## 18.05.2019 - Online