Android 6.0 permissions handling for location and Audio-Video notes plugin

This commit is contained in:
GaidamakUA 2015-12-04 11:26:41 +02:00
parent 233cec7962
commit 8ca050b01b
6 changed files with 196 additions and 84 deletions

View file

@ -25,5 +25,7 @@
<string name="tag_poi_name">name</string> <string name="tag_poi_name">name</string>
<string name="hint_tag">Tag</string> <string name="hint_tag">Tag</string>
<string name="hint_value">Value</string> <string name="hint_value">Value</string>
<string name="no_location_permission">App have no permission to access location data.</string>
<string name="no_camera_permission">App have no permission to access camera.</string>
<string name="no_microphone_permission">App have no permission to access microphone.</string>
</resources> </resources>

View file

@ -1,8 +1,10 @@
package net.osmand.plus; package net.osmand.plus;
import android.Manifest;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.GeomagneticField; import android.hardware.GeomagneticField;
import android.hardware.Sensor; import android.hardware.Sensor;
import android.hardware.SensorEvent; import android.hardware.SensorEvent;
@ -17,8 +19,11 @@ import android.location.LocationManager;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings; import android.provider.Settings;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.util.Log; import android.util.Log;
import android.widget.Toast;
import net.osmand.GeoidAltitudeCorrection; import net.osmand.GeoidAltitudeCorrection;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
import net.osmand.ResultMatcher; import net.osmand.ResultMatcher;
@ -40,7 +45,9 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
public class OsmAndLocationProvider implements SensorEventListener { public class OsmAndLocationProvider implements SensorEventListener {
public static final int REQUEST_LOCATION_PERMISSION = 100;
private static final String SIMULATED_PROVIDER = "OsmAnd"; private static final String SIMULATED_PROVIDER = "OsmAnd";
@ -76,7 +83,7 @@ public class OsmAndLocationProvider implements SensorEventListener {
private static final boolean USE_KALMAN_FILTER = true; private static final boolean USE_KALMAN_FILTER = true;
private static final float KALMAN_COEFFICIENT = 0.04f; private static final float KALMAN_COEFFICIENT = 0.04f;
float avgValSin = 0; float avgValSin = 0;
float avgValCos = 0; float avgValCos = 0;
float lastValSin = 0; float lastValSin = 0;
@ -86,7 +93,7 @@ public class OsmAndLocationProvider implements SensorEventListener {
private int previousCompassIndA = 0; private int previousCompassIndA = 0;
private int previousCompassIndB = 0; private int previousCompassIndB = 0;
private boolean inUpdateValue = false; private boolean inUpdateValue = false;
private Float heading = null; private Float heading = null;
// Current screen orientation // Current screen orientation
@ -94,22 +101,22 @@ public class OsmAndLocationProvider implements SensorEventListener {
private OsmandApplication app; private OsmandApplication app;
private OsmandSettings settings; private OsmandSettings settings;
private NavigationInfo navigationInfo; private NavigationInfo navigationInfo;
private CurrentPositionHelper currentPositionHelper; private CurrentPositionHelper currentPositionHelper;
private OsmAndLocationSimulation locationSimulation; private OsmAndLocationSimulation locationSimulation;
private net.osmand.Location location = null; private net.osmand.Location location = null;
private GPSInfo gpsInfo = new GPSInfo(); private GPSInfo gpsInfo = new GPSInfo();
private List<OsmAndLocationListener> locationListeners = new ArrayList<OsmAndLocationProvider.OsmAndLocationListener>(); private List<OsmAndLocationListener> locationListeners = new ArrayList<OsmAndLocationProvider.OsmAndLocationListener>();
private List<OsmAndCompassListener> compassListeners = new ArrayList<OsmAndLocationProvider.OsmAndCompassListener>(); private List<OsmAndCompassListener> compassListeners = new ArrayList<OsmAndLocationProvider.OsmAndCompassListener>();
private Listener gpsStatusListener; private Listener gpsStatusListener;
private float[] mRotationM = new float[9]; private float[] mRotationM = new float[9];
private OsmandPreference<Boolean> USE_MAGNETIC_FIELD_SENSOR_COMPASS; private OsmandPreference<Boolean> USE_MAGNETIC_FIELD_SENSOR_COMPASS;
private OsmandPreference<Boolean> USE_FILTER_FOR_COMPASS; private OsmandPreference<Boolean> USE_FILTER_FOR_COMPASS;
private static final long AGPS_TO_REDOWNLOAD = 16 * 60 * 60 * 1000; // 16 hours private static final long AGPS_TO_REDOWNLOAD = 16 * 60 * 60 * 1000; // 16 hours
public class SimulationProvider { public class SimulationProvider {
@ -118,14 +125,14 @@ public class OsmAndLocationProvider implements SensorEventListener {
private QuadPoint currentPoint; private QuadPoint currentPoint;
private net.osmand.Location startLocation; private net.osmand.Location startLocation;
private List<RouteSegmentResult> roads; private List<RouteSegmentResult> roads;
public void startSimulation(List<RouteSegmentResult> roads, public void startSimulation(List<RouteSegmentResult> roads,
net.osmand.Location currentLocation) { net.osmand.Location currentLocation) {
this.roads = roads; this.roads = roads;
startLocation = new net.osmand.Location(currentLocation); startLocation = new net.osmand.Location(currentLocation);
long ms = System.currentTimeMillis(); long ms = System.currentTimeMillis();
if(ms - startLocation.getTime() > 5000 || if (ms - startLocation.getTime() > 5000 ||
ms < startLocation.getTime()) { ms < startLocation.getTime()) {
startLocation.setTime(ms); startLocation.setTime(ms);
} }
@ -133,14 +140,14 @@ public class OsmAndLocationProvider implements SensorEventListener {
int px = MapUtils.get31TileNumberX(currentLocation.getLongitude()); int px = MapUtils.get31TileNumberX(currentLocation.getLongitude());
int py = MapUtils.get31TileNumberY(currentLocation.getLatitude()); int py = MapUtils.get31TileNumberY(currentLocation.getLatitude());
double dist = 1000; double dist = 1000;
for(int i = 0; i < roads.size(); i++) { for (int i = 0; i < roads.size(); i++) {
RouteSegmentResult road = roads.get(i); RouteSegmentResult road = roads.get(i);
boolean plus = road.getStartPointIndex() < road.getEndPointIndex(); boolean plus = road.getStartPointIndex() < road.getEndPointIndex();
for(int j = road.getStartPointIndex() + 1; j <= road.getEndPointIndex(); ) { for (int j = road.getStartPointIndex() + 1; j <= road.getEndPointIndex(); ) {
RouteDataObject obj = road.getObject(); RouteDataObject obj = road.getObject();
QuadPoint proj = MapUtils.getProjectionPoint31(px, py, obj.getPoint31XTile(j-1), obj.getPoint31YTile(j-1), QuadPoint proj = MapUtils.getProjectionPoint31(px, py, obj.getPoint31XTile(j - 1), obj.getPoint31YTile(j - 1),
obj.getPoint31XTile(j), obj.getPoint31YTile(j)); obj.getPoint31XTile(j), obj.getPoint31YTile(j));
double dd = MapUtils.squareRootDist31((int)proj.x, (int)proj.y, px, py); double dd = MapUtils.squareRootDist31((int) proj.x, (int) proj.y, px, py);
if (dd < dist) { if (dd < dist) {
dist = dd; dist = dd;
currentRoad = i; currentRoad = i;
@ -151,26 +158,26 @@ public class OsmAndLocationProvider implements SensorEventListener {
} }
} }
} }
private float proceedMeters(float meters, net.osmand.Location l) { private float proceedMeters(float meters, net.osmand.Location l) {
for(int i = currentRoad; i < roads.size(); i++) { for (int i = currentRoad; i < roads.size(); i++) {
RouteSegmentResult road = roads.get(i); RouteSegmentResult road = roads.get(i);
boolean firstRoad = i == currentRoad; boolean firstRoad = i == currentRoad;
boolean plus = road.getStartPointIndex() < road.getEndPointIndex(); boolean plus = road.getStartPointIndex() < road.getEndPointIndex();
for(int j = firstRoad ? currentSegment : road.getStartPointIndex() + 1; j <= road.getEndPointIndex(); ) { for (int j = firstRoad ? currentSegment : road.getStartPointIndex() + 1; j <= road.getEndPointIndex(); ) {
RouteDataObject obj = road.getObject(); RouteDataObject obj = road.getObject();
int st31x = obj.getPoint31XTile(j-1); int st31x = obj.getPoint31XTile(j - 1);
int st31y = obj.getPoint31YTile(j-1); int st31y = obj.getPoint31YTile(j - 1);
int end31x = obj.getPoint31XTile(j); int end31x = obj.getPoint31XTile(j);
int end31y = obj.getPoint31YTile(j); int end31y = obj.getPoint31YTile(j);
boolean last = i == roads.size() - 1 && j == road.getEndPointIndex(); boolean last = i == roads.size() - 1 && j == road.getEndPointIndex();
boolean first = firstRoad && j == currentSegment; boolean first = firstRoad && j == currentSegment;
if(first) { if (first) {
st31x = (int) currentPoint.x; st31x = (int) currentPoint.x;
st31y = (int) currentPoint.y; st31y = (int) currentPoint.y;
} }
double dd = MapUtils.measuredDist31(st31x, st31y, end31x, end31y); double dd = MapUtils.measuredDist31(st31x, st31y, end31x, end31y);
if(meters > dd && !last){ if (meters > dd && !last) {
meters -= dd; meters -= dd;
} else { } else {
int prx = (int) (st31x + (end31x - st31x) * (meters / dd)); int prx = (int) (st31x + (end31x - st31x) * (meters / dd));
@ -184,32 +191,32 @@ public class OsmAndLocationProvider implements SensorEventListener {
} }
return -1; return -1;
} }
/** /**
* @return null if it is not available of far from boundaries * @return null if it is not available of far from boundaries
*/ */
public net.osmand.Location getSimulatedLocation() { public net.osmand.Location getSimulatedLocation() {
if(!isSimulatedDataAvailable()) { if (!isSimulatedDataAvailable()) {
return null; return null;
} }
net.osmand.Location loc = new net.osmand.Location(SIMULATED_PROVIDER); net.osmand.Location loc = new net.osmand.Location(SIMULATED_PROVIDER);
loc.setSpeed(startLocation.getSpeed()); loc.setSpeed(startLocation.getSpeed());
loc.setAltitude(startLocation.getAltitude()); loc.setAltitude(startLocation.getAltitude());
loc.setTime(System.currentTimeMillis()); loc.setTime(System.currentTimeMillis());
float meters = startLocation.getSpeed() * ((System.currentTimeMillis() - startLocation.getTime()) / 1000); float meters = startLocation.getSpeed() * ((System.currentTimeMillis() - startLocation.getTime()) / 1000);
float proc = proceedMeters(meters, loc); float proc = proceedMeters(meters, loc);
if(proc < 0 || proc >= 100){ if (proc < 0 || proc >= 100) {
return null; return null;
} }
return loc; return loc;
} }
public boolean isSimulatedDataAvailable() { public boolean isSimulatedDataAvailable() {
return startLocation != null && startLocation.getSpeed() > 0 && currentRoad >= 0; return startLocation != null && startLocation.getSpeed() > 0 && currentRoad >= 0;
} }
} }
public OsmAndLocationProvider(OsmandApplication app) { public OsmAndLocationProvider(OsmandApplication app) {
this.app = app; this.app = app;
navigationInfo = new NavigationInfo(app); navigationInfo = new NavigationInfo(app);
@ -219,39 +226,41 @@ public class OsmAndLocationProvider implements SensorEventListener {
currentPositionHelper = new CurrentPositionHelper(app); currentPositionHelper = new CurrentPositionHelper(app);
locationSimulation = new OsmAndLocationSimulation(app, this); locationSimulation = new OsmAndLocationSimulation(app, this);
} }
public void resumeAllUpdates() { public void resumeAllUpdates() {
final LocationManager service = (LocationManager) app.getSystemService(Context.LOCATION_SERVICE); final LocationManager service = (LocationManager) app.getSystemService(Context.LOCATION_SERVICE);
if(app.getSettings().isInternetConnectionAvailable()) { if (app.getSettings().isInternetConnectionAvailable()) {
if(System.currentTimeMillis() - app.getSettings().AGPS_DATA_LAST_TIME_DOWNLOADED.get() > AGPS_TO_REDOWNLOAD) { if (System.currentTimeMillis() - app.getSettings().AGPS_DATA_LAST_TIME_DOWNLOADED.get() > AGPS_TO_REDOWNLOAD) {
//force an updated check for internet connectivity here before destroying A-GPS-data //force an updated check for internet connectivity here before destroying A-GPS-data
if(app.getSettings().isInternetConnectionAvailable(true)) { if (app.getSettings().isInternetConnectionAvailable(true)) {
redownloadAGPS(); redownloadAGPS();
} }
} }
} }
service.addGpsStatusListener(getGpsStatusListener(service)); if (isLocationPermissionAvailable(app)) {
try { service.addGpsStatusListener(getGpsStatusListener(service));
service.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, gpsListener);
} catch (IllegalArgumentException e) {
Log.d(PlatformUtil.TAG, "GPS location provider not available"); //$NON-NLS-1$
}
// try to always ask for network provide : it is faster way to find location
List<String> providers = service.getProviders(true);
if(providers == null) {
return;
}
for (String provider : providers) {
if (provider == null || provider.equals(LocationManager.GPS_PROVIDER)) {
continue;
}
try { try {
NetworkListener networkListener = new NetworkListener(); service.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, gpsListener);
service.requestLocationUpdates(provider, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, networkListener);
networkListeners.add(networkListener);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
Log.d(PlatformUtil.TAG, provider + " location provider not available"); //$NON-NLS-1$ Log.d(PlatformUtil.TAG, "GPS location provider not available"); //$NON-NLS-1$
}
// try to always ask for network provide : it is faster way to find location
List<String> providers = service.getProviders(true);
if (providers == null) {
return;
}
for (String provider : providers) {
if (provider == null || provider.equals(LocationManager.GPS_PROVIDER)) {
continue;
}
try {
NetworkListener networkListener = new NetworkListener();
service.requestLocationUpdates(provider, GPS_TIMEOUT_REQUEST, GPS_DIST_REQUEST, networkListener);
networkListeners.add(networkListener);
} catch (IllegalArgumentException e) {
Log.d(PlatformUtil.TAG, provider + " location provider not available"); //$NON-NLS-1$
}
} }
} }
} }
@ -332,6 +341,9 @@ public class OsmAndLocationProvider implements SensorEventListener {
} }
public net.osmand.Location getFirstTimeRunDefaultLocation() { public net.osmand.Location getFirstTimeRunDefaultLocation() {
if (!isLocationPermissionAvailable(app)) {
return null;
}
LocationManager service = (LocationManager) app.getSystemService(Context.LOCATION_SERVICE); LocationManager service = (LocationManager) app.getSystemService(Context.LOCATION_SERVICE);
List<String> ps = service.getProviders(true); List<String> ps = service.getProviders(true);
if(ps == null) { if(ps == null) {
@ -914,4 +926,12 @@ public class OsmAndLocationProvider implements SensorEventListener {
return true; return true;
} }
public static boolean isLocationPermissionAvailable(Context context) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
Toast.makeText(context, R.string.no_location_permission, Toast.LENGTH_LONG).show();
return false;
}
return true;
}
} }

View file

@ -211,6 +211,17 @@ public abstract class OsmandPlugin {
public void mapActivityScreenOff(MapActivity activity) { public void mapActivityScreenOff(MapActivity activity) {
} }
public void handleRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults, MapActivity activity) {
}
public static final void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults, MapActivity activity) {
for (OsmandPlugin plugin : getAvailablePlugins()) {
plugin.handleRequestPermissionsResult(requestCode, permissions, grantResults, activity);
}
}
public boolean destinationReached() { public boolean destinationReached() {
return true; return true;
} }
@ -443,5 +454,4 @@ public abstract class OsmandPlugin {
p.addMyPlacesTab(favoritesActivity, mTabs, intent); p.addMyPlacesTab(favoritesActivity, mTabs, intent);
} }
} }
} }

View file

@ -16,6 +16,7 @@ import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.NotificationCompat.Builder; import android.support.v4.app.NotificationCompat.Builder;
import android.support.v4.widget.DrawerLayout; import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.NotificationCompat; import android.support.v7.app.NotificationCompat;
@ -95,7 +96,8 @@ import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class MapActivity extends AccessibleActivity implements DownloadEvents { public class MapActivity extends AccessibleActivity implements DownloadEvents,
ActivityCompat.OnRequestPermissionsResultCallback {
private static final int SHOW_POSITION_MSG_ID = OsmAndConstants.UI_HANDLER_MAP_VIEW + 1; private static final int SHOW_POSITION_MSG_ID = OsmAndConstants.UI_HANDLER_MAP_VIEW + 1;
private static final int LONG_KEYPRESS_MSG_ID = OsmAndConstants.UI_HANDLER_MAP_VIEW + 2; private static final int LONG_KEYPRESS_MSG_ID = OsmAndConstants.UI_HANDLER_MAP_VIEW + 2;
private static final int LONG_KEYPRESS_DELAY = 500; private static final int LONG_KEYPRESS_DELAY = 500;
@ -176,7 +178,7 @@ public class MapActivity extends AccessibleActivity implements DownloadEvents {
mapView = new OsmandMapTileView(this, getWindow().getDecorView().getWidth(), mapView = new OsmandMapTileView(this, getWindow().getDecorView().getWidth(),
getWindow().getDecorView().getHeight()); getWindow().getDecorView().getHeight());
if(app.getAppInitializer().checkAppVersionChanged(this)) { if (app.getAppInitializer().checkAppVersionChanged(this)) {
new WhatsNewDialogFragment().show(getSupportFragmentManager(), null); new WhatsNewDialogFragment().show(getSupportFragmentManager(), null);
} }
mapActions = new MapActivityActions(this); mapActions = new MapActivityActions(this);
@ -668,7 +670,7 @@ public class MapActivity extends AccessibleActivity implements DownloadEvents {
} }
} }
wakeLockHelper.onStop(this); wakeLockHelper.onStop(this);
if(getMyApplication().getNavigationService() == null) { if (getMyApplication().getNavigationService() == null) {
getMyApplication().getNotificationHelper().removeServiceNotificationCompletely(); getMyApplication().getNotificationHelper().removeServiceNotificationCompletely();
} }
super.onStop(); super.onStop();
@ -687,7 +689,6 @@ public class MapActivity extends AccessibleActivity implements DownloadEvents {
if (atlasMapRendererView != null) { if (atlasMapRendererView != null) {
atlasMapRendererView.handleOnDestroy(); atlasMapRendererView.handleOnDestroy();
} }
} }
private void cancelNotification() { private void cancelNotification() {
@ -1054,6 +1055,12 @@ public class MapActivity extends AccessibleActivity implements DownloadEvents {
} }
} }
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
OsmandPlugin.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
private class ScreenOffReceiver extends BroadcastReceiver { private class ScreenOffReceiver extends BroadcastReceiver {
@Override @Override

View file

@ -1,5 +1,6 @@
package net.osmand.plus.audionotes; package net.osmand.plus.audionotes;
import android.Manifest;
import android.app.Activity; import android.app.Activity;
import android.app.Dialog; import android.app.Dialog;
import android.content.ComponentName; import android.content.ComponentName;
@ -7,6 +8,7 @@ import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener; import android.content.DialogInterface.OnClickListener;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options; import android.graphics.BitmapFactory.Options;
@ -23,6 +25,7 @@ import android.media.SoundPool;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.view.Display; import android.view.Display;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.Surface; import android.view.Surface;
@ -93,6 +96,9 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
public static final String MPEG4_EXTENSION = "mp4"; public static final String MPEG4_EXTENSION = "mp4";
public static final String IMG_EXTENSION = "jpg"; public static final String IMG_EXTENSION = "jpg";
private static final Log log = PlatformUtil.getLog(AudioVideoNotesPlugin.class); private static final Log log = PlatformUtil.getLog(AudioVideoNotesPlugin.class);
public static final int CAMERA_FOR_VIDEO_REQUEST_CODE = 101;
public static final int CAMERA_FOR_PHOTO_REQUEST_CODE = 102;
public static final int AUDIO_REQUEST_CODE = 103;
private static Method mRegisterMediaButtonEventReceiver; private static Method mRegisterMediaButtonEventReceiver;
private static Method mUnregisterMediaButtonEventReceiver; private static Method mUnregisterMediaButtonEventReceiver;
private OsmandApplication app; private OsmandApplication app;
@ -140,6 +146,8 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
private File lastTakingPhoto; private File lastTakingPhoto;
private final static char SPLIT_DESC = ' '; private final static char SPLIT_DESC = ' ';
private double tempLat;
private double tempLon;
public static class Recording { public static class Recording {
public Recording(File f) { public Recording(File f) {
@ -463,6 +471,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
public String getHelpFileName() { public String getHelpFileName() {
return "feature_articles/audio-video-notes-plugin.html"; return "feature_articles/audio-video-notes-plugin.html";
} }
@Override @Override
public boolean init(final OsmandApplication app, Activity activity) { public boolean init(final OsmandApplication app, Activity activity) {
initializeRemoteControlRegistrationMethods(); initializeRemoteControlRegistrationMethods();
@ -722,7 +731,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
((AudioManager) activity.getSystemService(Context.AUDIO_SERVICE)).registerMediaButtonEventReceiver( ((AudioManager) activity.getSystemService(Context.AUDIO_SERVICE)).registerMediaButtonEventReceiver(
new ComponentName(activity, MediaRemoteControlReceiver.class)); new ComponentName(activity, MediaRemoteControlReceiver.class));
} }
@Override @Override
public void mapActivityPause(MapActivity activity) { public void mapActivityPause(MapActivity activity) {
this.mapActivity = null; this.mapActivity = null;
@ -733,7 +742,18 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
if (AV_EXTERNAL_RECORDER.get()) { if (AV_EXTERNAL_RECORDER.get()) {
captureVideoExternal(lat, lon, mapActivity); captureVideoExternal(lat, lon, mapActivity);
} else { } else {
recordVideoCamera(lat, lon, mapActivity); if (ActivityCompat.checkSelfPermission(mapActivity, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(mapActivity, Manifest.permission.RECORD_AUDIO)
== PackageManager.PERMISSION_GRANTED) {
recordVideoCamera(lat, lon, mapActivity);
} else {
tempLat = lat;
tempLon = lon;
ActivityCompat.requestPermissions(mapActivity,
new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO},
CAMERA_FOR_VIDEO_REQUEST_CODE);
}
} }
} }
@ -830,34 +850,55 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
} }
public void recordAudio(double lat, double lon, final MapActivity mapActivity) { public void recordAudio(double lat, double lon, final MapActivity mapActivity) {
MediaRecorder mr = new MediaRecorder(); if (ActivityCompat.checkSelfPermission(mapActivity, Manifest.permission.RECORD_AUDIO)
final File f = getBaseFileName(lat, lon, app, THREEGP_EXTENSION); == PackageManager.PERMISSION_GRANTED) {
mr.setAudioSource(MediaRecorder.AudioSource.MIC); MediaRecorder mr = new MediaRecorder();
mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); final File f = getBaseFileName(lat, lon, app, THREEGP_EXTENSION);
mr.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); mr.setAudioSource(MediaRecorder.AudioSource.MIC);
mr.setOutputFile(f.getAbsolutePath()); mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
try { mr.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
runMediaRecorder(mapActivity, mr, f); mr.setOutputFile(f.getAbsolutePath());
} catch (Exception e) { try {
log.error("Error starting audio recorder ", e); runMediaRecorder(mapActivity, mr, f);
AccessibleToast.makeText(app, app.getString(R.string.recording_error) + " : " + e.getMessage(), Toast.LENGTH_LONG).show(); } catch (Exception e) {
log.error("Error starting audio recorder ", e);
AccessibleToast.makeText(app, app.getString(R.string.recording_error) + " : " + e.getMessage(), Toast.LENGTH_LONG).show();
}
} else {
tempLat = lat;
tempLon = lon;
ActivityCompat.requestPermissions(mapActivity,
new String[]{Manifest.permission.RECORD_AUDIO},
AUDIO_REQUEST_CODE);
} }
} }
public void takePhoto(final double lat, final double lon, final MapActivity mapActivity) { public void takePhoto(final double lat, final double lon, final MapActivity mapActivity) {
if (AV_EXTERNAL_PHOTO_CAM.get()) { if (AV_EXTERNAL_PHOTO_CAM.get()) {
takeIntentPhoto(lat, lon, mapActivity); takePhotoExternal(lat, lon, mapActivity);
} else { } else {
final Camera cam = openCamera(); if (ActivityCompat.checkSelfPermission(mapActivity, Manifest.permission.CAMERA)
if (cam != null) { == PackageManager.PERMISSION_GRANTED) {
takePhotoWithCamera(lat, lon, mapActivity, cam); takePhotoInternalOrExternal(lat, lon, mapActivity);
} else { } else {
takeIntentPhoto(lat, lon, mapActivity); tempLat = lat;
tempLon = lon;
ActivityCompat.requestPermissions(mapActivity,
new String[]{Manifest.permission.CAMERA},
CAMERA_FOR_PHOTO_REQUEST_CODE);
} }
} }
} }
private void takePhotoInternalOrExternal(double lat, double lon, MapActivity mapActivity) {
final Camera cam = openCamera();
if (cam != null) {
takePhotoWithCamera(lat, lon, mapActivity, cam);
} else {
takePhotoExternal(lat, lon, mapActivity);
}
}
private void takePhotoWithCamera(final double lat, final double lon, final MapActivity mapActivity, final Camera cam) { private void takePhotoWithCamera(final double lat, final double lon, final MapActivity mapActivity, final Camera cam) {
try { try {
final Dialog dlg = new Dialog(mapActivity); final Dialog dlg = new Dialog(mapActivity);
@ -1012,7 +1053,7 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
} }
} }
private void takeIntentPhoto(double lat, double lon, final MapActivity mapActivity) { private void takePhotoExternal(double lat, double lon, final MapActivity mapActivity) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
final File f = getBaseFileName(lat, lon, app, IMG_EXTENSION); final File f = getBaseFileName(lat, lon, app, IMG_EXTENSION);
lastTakingPhoto = f; lastTakingPhoto = f;
@ -1327,6 +1368,31 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
return false; return false;
} }
@Override
public void handleRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults, MapActivity activity) {
if (requestCode == CAMERA_FOR_VIDEO_REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
recordVideoCamera(tempLat, tempLon, activity);
} else {
app.showToastMessage(R.string.no_camera_permission);
}
} else if (requestCode == CAMERA_FOR_PHOTO_REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
takePhotoInternalOrExternal(tempLat, tempLon, activity);
} else {
app.showToastMessage(R.string.no_camera_permission);
}
} else if (requestCode == AUDIO_REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
recordAudio(tempLat, tempLon, activity);
} else {
app.showToastMessage(R.string.no_microphone_permission);
}
}
}
public class AudioVideoPhotoHandler implements PictureCallback { public class AudioVideoPhotoHandler implements PictureCallback {
private File pictureFile; private File pictureFile;
private Dialog dlg; private Dialog dlg;

View file

@ -1,5 +1,6 @@
package net.osmand.plus.views; package net.osmand.plus.views;
import android.Manifest;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
@ -11,6 +12,7 @@ import android.graphics.drawable.Drawable;
import android.os.Build; import android.os.Build;
import android.os.Handler; import android.os.Handler;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
@ -28,6 +30,7 @@ import net.osmand.core.android.MapRendererContext;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.data.RotatedTileBox; import net.osmand.data.RotatedTileBox;
import net.osmand.plus.ApplicationMode; import net.osmand.plus.ApplicationMode;
import net.osmand.plus.OsmAndLocationProvider;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin; import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.OsmandSettings; import net.osmand.plus.OsmandSettings;
@ -406,7 +409,13 @@ public class MapControlsLayer extends OsmandMapLayer {
backToLocation.setOnClickListener(new View.OnClickListener() { backToLocation.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
mapActivity.getMapViewTrackingUtilities().backToLocationImpl(); if(OsmAndLocationProvider.isLocationPermissionAvailable(mapActivity)) {
mapActivity.getMapViewTrackingUtilities().backToLocationImpl();
} else {
ActivityCompat.requestPermissions(mapActivity,
new String[] {Manifest.permission.ACCESS_FINE_LOCATION},
OsmAndLocationProvider.REQUEST_LOCATION_PERMISSION);
}
} }
}); });
controls.add(createHudButton(mapActivity.findViewById(R.id.map_app_mode_shadow), 0).setBg( controls.add(createHudButton(mapActivity.findViewById(R.id.map_app_mode_shadow), 0).setBg(
@ -444,7 +453,7 @@ public class MapControlsLayer extends OsmandMapLayer {
zoomText = (TextView) mapActivity.findViewById(R.id.map_app_mode_text); zoomText = (TextView) mapActivity.findViewById(R.id.map_app_mode_text);
View routePlanButton = mapActivity.findViewById(R.id.map_route_info_button); View routePlanButton = mapActivity.findViewById(R.id.map_route_info_button);
routePlanningBtn = createHudButton((ImageView) routePlanButton, R.drawable.map_directions).setBg( routePlanningBtn = createHudButton(routePlanButton, R.drawable.map_directions).setBg(
R.drawable.btn_round, R.drawable.btn_round_night); R.drawable.btn_round, R.drawable.btn_round_night);
controls.add(routePlanningBtn); controls.add(routePlanningBtn);
routePlanButton.setOnClickListener(new View.OnClickListener() { routePlanButton.setOnClickListener(new View.OnClickListener() {
@ -1021,6 +1030,4 @@ public class MapControlsLayer extends OsmandMapLayer {
} }
} }
} }
} }