From c526599e204aa27aafd4779905acff6dc5cc7090 Mon Sep 17 00:00:00 2001
From: Emux <devemux86@gmail.com>
Date: Mon, 17 Jun 2019 11:11:05 +0300
Subject: [PATCH] Android 10 targetSdkVersion with runtime permissions, #728

---
 build.gradle                                  |  2 +-
 gradle.properties                             |  2 ++
 vtm-android-example/AndroidManifest.xml       |  1 -
 .../oscim/android/filepicker/FilePicker.java  |  4 +--
 .../oscim/android/test/LocationActivity.java  | 31 ++++++++++++++-----
 .../android/test/LocationTextureActivity.java | 31 ++++++++++++++-----
 vtm-app/AndroidManifest.xml                   |  1 -
 vtm-app/src/org/oscim/app/MapLayers.java      |  4 +--
 vtm-app/src/org/oscim/app/TileMap.java        |  9 +++++-
 .../org/oscim/app/filepicker/FilePicker.java  | 14 ++++-----
 10 files changed, 68 insertions(+), 31 deletions(-)

diff --git a/build.gradle b/build.gradle
index 3c9c0f3f..1cd61cf7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -33,7 +33,7 @@ static def androidCompileSdk() { return 29 }
 // 14 for Support Library, 16 for sqlite-android
 static def androidMinSdk() { return 16 }
 
-static def androidTargetSdk() { return 22 }
+static def androidTargetSdk() { return 29 }
 
 static def versionCode() { return 1 }
 
diff --git a/gradle.properties b/gradle.properties
index 743d692c..9592636c 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -11,3 +11,5 @@ org.gradle.jvmargs=-Xmx1536m
 # This option should only be used with decoupled projects. More details, visit
 # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
 # org.gradle.parallel=true
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/vtm-android-example/AndroidManifest.xml b/vtm-android-example/AndroidManifest.xml
index bbc07a7e..03c0762c 100644
--- a/vtm-android-example/AndroidManifest.xml
+++ b/vtm-android-example/AndroidManifest.xml
@@ -7,7 +7,6 @@
 
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
     <uses-permission android:name="android.permission.INTERNET" />
-    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
 
     <application
         android:allowBackup="true"
diff --git a/vtm-android-example/src/org/oscim/android/filepicker/FilePicker.java b/vtm-android-example/src/org/oscim/android/filepicker/FilePicker.java
index 982813b6..55b8e01c 100755
--- a/vtm-android-example/src/org/oscim/android/filepicker/FilePicker.java
+++ b/vtm-android-example/src/org/oscim/android/filepicker/FilePicker.java
@@ -162,7 +162,7 @@ public class FilePicker extends Activity implements AdapterView.OnItemClickListe
         }
 
         // if a parent directory exists, add it at the first position
-        if (mDirectory.getParentFile() != null) {
+        if (mDirectory.getParentFile() != null && mDirectory.getParentFile().canRead()) {
             mFilesWithParentFolder = new File[mFiles.length + 1];
             mFilesWithParentFolder[0] = mDirectory.getParentFile();
             System.arraycopy(mFiles, 0, mFilesWithParentFolder, 1,
@@ -180,7 +180,7 @@ public class FilePicker extends Activity implements AdapterView.OnItemClickListe
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_file_picker);
 
-        mDefaultDirectory = getExternalFilesDir(null).getAbsolutePath();
+        mDefaultDirectory = getExternalFilesDir(null) != null ? getExternalFilesDir(null).getAbsolutePath() : "/sdcard/";
         mFilePickerIconAdapter = new FilePickerIconAdapter(this);
         GridView gridView = (GridView) findViewById(R.id.filePickerView);
         gridView.setOnItemClickListener(this);
diff --git a/vtm-android-example/src/org/oscim/android/test/LocationActivity.java b/vtm-android-example/src/org/oscim/android/test/LocationActivity.java
index 7c4692ae..40e2fc1c 100644
--- a/vtm-android-example/src/org/oscim/android/test/LocationActivity.java
+++ b/vtm-android-example/src/org/oscim/android/test/LocationActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2018 devemux86
+ * Copyright 2016-2019 devemux86
  *
  * This program is free software: you can redistribute it and/or modify it under the
  * terms of the GNU Lesser General Public License as published by the Free Software
@@ -14,12 +14,14 @@
  */
 package org.oscim.android.test;
 
+import android.Manifest;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.location.Location;
 import android.location.LocationListener;
 import android.location.LocationManager;
+import android.os.Build;
 import android.os.Bundle;
-
 import org.oscim.core.MapPosition;
 import org.oscim.layers.LocationLayer;
 
@@ -41,17 +43,25 @@ public class LocationActivity extends BitmapTileActivity implements LocationList
     }
 
     @Override
-    protected void onResume() {
-        super.onResume();
+    public void onRequestPermissionsResult(final int requestCode, final String[] permissions, final int[] grantResults) {
+        if (requestCode == 0) {
+            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
+                enableAvailableProviders();
+        }
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
 
         enableAvailableProviders();
     }
 
     @Override
-    protected void onPause() {
-        super.onPause();
-
+    public void onStop() {
         locationManager.removeUpdates(this);
+
+        super.onStop();
     }
 
     @Override
@@ -78,6 +88,13 @@ public class LocationActivity extends BitmapTileActivity implements LocationList
     }
 
     private void enableAvailableProviders() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
+                requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 0);
+                return;
+            }
+        }
+
         locationManager.removeUpdates(this);
 
         for (String provider : locationManager.getProviders(true)) {
diff --git a/vtm-android-example/src/org/oscim/android/test/LocationTextureActivity.java b/vtm-android-example/src/org/oscim/android/test/LocationTextureActivity.java
index 596b17d4..2377bad0 100644
--- a/vtm-android-example/src/org/oscim/android/test/LocationTextureActivity.java
+++ b/vtm-android-example/src/org/oscim/android/test/LocationTextureActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2018 devemux86
+ * Copyright 2016-2019 devemux86
  * Copyright 2018 Longri
  *
  * This program is free software: you can redistribute it and/or modify it under the
@@ -15,12 +15,14 @@
  */
 package org.oscim.android.test;
 
+import android.Manifest;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.location.Location;
 import android.location.LocationListener;
 import android.location.LocationManager;
+import android.os.Build;
 import android.os.Bundle;
-
 import org.oscim.backend.CanvasAdapter;
 import org.oscim.backend.canvas.Bitmap;
 import org.oscim.backend.canvas.Color;
@@ -78,17 +80,25 @@ public class LocationTextureActivity extends BitmapTileActivity implements Locat
     }
 
     @Override
-    protected void onResume() {
-        super.onResume();
+    public void onRequestPermissionsResult(final int requestCode, final String[] permissions, final int[] grantResults) {
+        if (requestCode == 0) {
+            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
+                enableAvailableProviders();
+        }
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
 
         enableAvailableProviders();
     }
 
     @Override
-    protected void onPause() {
-        super.onPause();
-
+    public void onStop() {
         locationManager.removeUpdates(this);
+
+        super.onStop();
     }
 
     @Override
@@ -115,6 +125,13 @@ public class LocationTextureActivity extends BitmapTileActivity implements Locat
     }
 
     private void enableAvailableProviders() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
+                requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 0);
+                return;
+            }
+        }
+
         locationManager.removeUpdates(this);
 
         for (String provider : locationManager.getProviders(true)) {
diff --git a/vtm-app/AndroidManifest.xml b/vtm-app/AndroidManifest.xml
index 3881a03f..26186026 100644
--- a/vtm-app/AndroidManifest.xml
+++ b/vtm-app/AndroidManifest.xml
@@ -9,7 +9,6 @@
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.VIBRATE" />
-    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
 
     <application
         android:name=".App"
diff --git a/vtm-app/src/org/oscim/app/MapLayers.java b/vtm-app/src/org/oscim/app/MapLayers.java
index 7fb18ef4..614e27fc 100644
--- a/vtm-app/src/org/oscim/app/MapLayers.java
+++ b/vtm-app/src/org/oscim/app/MapLayers.java
@@ -19,9 +19,7 @@ package org.oscim.app;
 
 import android.content.Context;
 import android.content.SharedPreferences;
-import android.os.Environment;
 import android.preference.PreferenceManager;
-
 import org.oscim.android.cache.TileCache;
 import org.oscim.layers.GenericLayer;
 import org.oscim.layers.Layer;
@@ -67,7 +65,7 @@ public class MapLayers {
         @Override
         TileSource init() {
             return new MapFileTileSource().setOption("file",
-                    new File(Environment.getExternalStorageDirectory(), "berlin.map").getAbsolutePath());
+                    new File("/sdcard/berlin.map").getAbsolutePath());
         }
     }, new Config("MAPNIK_VECTOR") {
         @Override
diff --git a/vtm-app/src/org/oscim/app/TileMap.java b/vtm-app/src/org/oscim/app/TileMap.java
index cc5a3134..42f81cb3 100755
--- a/vtm-app/src/org/oscim/app/TileMap.java
+++ b/vtm-app/src/org/oscim/app/TileMap.java
@@ -1,6 +1,6 @@
 /* Copyright 2010, 2011, 2012 mapsforge.org
  * Copyright 2012 Hannes Janetzek
- * Copyright 2016-2017 devemux86
+ * Copyright 2016-2019 devemux86
  *
  * This program is free software: you can redistribute it and/or modify it under the
  * terms of the GNU Lesser General Public License as published by the Free Software
@@ -15,11 +15,13 @@
  */
 package org.oscim.app;
 
+import android.Manifest;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
@@ -73,6 +75,11 @@ public class TileMap extends MapActivity implements MapEventsReceiver {
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
+                requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 0);
+        }
+
         setContentView(R.layout.activity_tilemap);
         App.view = (MapView) findViewById(R.id.mapView);
         registerMapView(App.view);
diff --git a/vtm-app/src/org/oscim/app/filepicker/FilePicker.java b/vtm-app/src/org/oscim/app/filepicker/FilePicker.java
index 77c31a3a..57799b90 100755
--- a/vtm-app/src/org/oscim/app/filepicker/FilePicker.java
+++ b/vtm-app/src/org/oscim/app/filepicker/FilePicker.java
@@ -1,6 +1,6 @@
 /*
  * Copyright 2010, 2011, 2012 mapsforge.org
- * Copyright 2016 devemux86
+ * Copyright 2016-2019 devemux86
  *
  * This program is free software: you can redistribute it and/or modify it under the
  * terms of the GNU Lesser General Public License as published by the Free Software
@@ -24,11 +24,9 @@ import android.content.SharedPreferences;
 import android.content.SharedPreferences.Editor;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.Environment;
 import android.view.View;
 import android.widget.AdapterView;
 import android.widget.GridView;
-
 import org.oscim.app.R;
 import org.oscim.app.filefilter.ValidFileFilter;
 
@@ -62,7 +60,6 @@ public class FilePicker extends Activity implements AdapterView.OnItemClickListe
     public static final String SELECTED_FILE = "selectedFile";
 
     private static final String CURRENT_DIRECTORY = "currentDirectory";
-    private static final String DEFAULT_DIRECTORY = Environment.getExternalStorageDirectory().getAbsolutePath();
     private static final int DIALOG_FILE_INVALID = 0;
     // private static final int DIALOG_FILE_SELECT = 1;
     private static Comparator<File> fileComparator = getDefaultFileComparator();
@@ -125,6 +122,7 @@ public class FilePicker extends Activity implements AdapterView.OnItemClickListe
     }
 
     private File currentDirectory;
+    private String defaultDirectory;
     private FilePickerIconAdapter filePickerIconAdapter;
     private File[] files;
     private File[] filesWithParentFolder;
@@ -166,7 +164,7 @@ public class FilePicker extends Activity implements AdapterView.OnItemClickListe
         }
 
         // if a parent directory exists, add it at the first position
-        if (this.currentDirectory.getParentFile() != null) {
+        if (this.currentDirectory.getParentFile() != null && this.currentDirectory.getParentFile().canRead()) {
             this.filesWithParentFolder = new File[this.files.length + 1];
             this.filesWithParentFolder[0] = this.currentDirectory.getParentFile();
             System.arraycopy(this.files, 0, this.filesWithParentFolder, 1,
@@ -184,6 +182,7 @@ public class FilePicker extends Activity implements AdapterView.OnItemClickListe
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_file_picker);
 
+        defaultDirectory = getExternalFilesDir(null) != null ? getExternalFilesDir(null).getAbsolutePath() : "/sdcard/";
         this.filePickerIconAdapter = new FilePickerIconAdapter(this);
         GridView gridView = (GridView) findViewById(R.id.filePickerView);
         gridView.setOnItemClickListener(this);
@@ -254,10 +253,9 @@ public class FilePicker extends Activity implements AdapterView.OnItemClickListe
         // restore the current directory
         SharedPreferences preferences = getSharedPreferences(PREFERENCES_FILE,
                 MODE_PRIVATE);
-        this.currentDirectory = new File(preferences.getString(CURRENT_DIRECTORY,
-                DEFAULT_DIRECTORY));
+        this.currentDirectory = new File(preferences.getString(CURRENT_DIRECTORY, defaultDirectory));
         if (!this.currentDirectory.exists() || !this.currentDirectory.canRead()) {
-            this.currentDirectory = new File(DEFAULT_DIRECTORY);
+            this.currentDirectory = new File(defaultDirectory);
         }
         browseToCurrentDirectory();
     }