From 2dd9c90688279396343d8d372c51a1f7bb147753 Mon Sep 17 00:00:00 2001 From: k3b <1374583+k3b@users.noreply.github.com> Date: Mon, 23 Mar 2020 20:38:00 +0100 Subject: [PATCH] #169: Update to android-9 sdk (API-28) + dynamic ask for WRITE_EXTERNAL_STORAGE --- app/build.gradle | 2 +- .../androFotoFinder/AndroFotoFinderApp.java | 2 - .../android/androFotoFinder/BaseActivity.java | 9 ++- .../k3b/android/androFotoFinder/Common.java | 2 + .../androFotoFinder/FotoGalleryActivity.java | 4 +- .../GalleryFilterActivity.java | 4 +- .../PhotoAutoprocessingEditActivity.java | 5 +- .../PhotoPropertiesEditActivity.java | 4 +- .../backup/BackupActivity.java | 4 +- .../ImageDetailActivityViewPager.java | 4 +- .../locationmap/MapGeoPickerActivity.java | 6 +- .../androFotoFinder/queries/FotoSql.java | 17 +++-- .../MediaContentproviderRepositoryImpl.java | 3 +- .../widget/FilePermissionActivity.java | 65 +++++++++++++++++-- app/src/main/res/values/strings.xml | 2 + 15 files changed, 92 insertions(+), 41 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 22998c1a..e19c9b2c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -21,7 +21,7 @@ android { // Android 6.0 Marshmallow (API 23); Android 7.0 Nougat (API 24) maxSdkVersion 28 // #155: android-10=api29 - targetSdkVersion 21 + targetSdkVersion 28 // non-fdroid release // appXXX are defined in gradle.properties diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/AndroFotoFinderApp.java b/app/src/main/java/de/k3b/android/androFotoFinder/AndroFotoFinderApp.java index 00ba24d7..51bee1d8 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/AndroFotoFinderApp.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/AndroFotoFinderApp.java @@ -222,8 +222,6 @@ private File getOutpuFile() { // #60: configure some of the mapsforge settings first MapsForgeSupport.createInstance(this); - FotoSql.deleteMediaWithNullPath(); - Log.i(Global.LOG_CONTEXT, getAppId() + " created"); } diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/BaseActivity.java b/app/src/main/java/de/k3b/android/androFotoFinder/BaseActivity.java index b995d08b..a7ca6091 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/BaseActivity.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/BaseActivity.java @@ -19,17 +19,17 @@ package de.k3b.android.androFotoFinder; +import android.os.Bundle; + import de.k3b.android.widget.ActivityWithAutoCloseDialogs; import de.k3b.android.widget.ActivityWithCallContext; import de.k3b.android.widget.BaseQueryActivity; import de.k3b.android.widget.FilePermissionActivity; import de.k3b.android.widget.LocalizedActivity; -import de.k3b.android.widget.PermissionBaseActivity; /** * Nearly all activities are inherited from {@link BaseActivity}. * * {@link FilePermissionActivity} manage permission write to external-storage and to sdcard - * * {@link PermissionBaseActivity} can Ask for permission * * {@link ActivityWithAutoCloseDialogs} Automatically closes pop-dialogs * * {@link LocalizedActivity} Change the locale (language) and translation of its content at runtime * * {@link ActivityWithCallContext} memorizes the activity call stack (parent Activities) for debugging purposes. @@ -39,4 +39,9 @@ * ** {@link de.k3b.android.androFotoFinder.locationmap.MapGeoPickerActivity} */ public abstract class BaseActivity extends FilePermissionActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + Global.debugMemory(Global.LOG_CONTEXT, "onCreate " + getClass().getSimpleName()); + super.onCreate(savedInstanceState); + } } diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/Common.java b/app/src/main/java/de/k3b/android/androFotoFinder/Common.java index 2d32a995..6b346210 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/Common.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/Common.java @@ -55,4 +55,6 @@ public interface Common { /** detail,geoEdit: Activity.onActivityResult() - resultCode: one or more photo-files were modified. caller must invalidate cached files/directories. */ int RESULT_CHANGE = Activity.RESULT_OK; + + int RESULT_NO_PERMISSIONS = -22; } diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/FotoGalleryActivity.java b/app/src/main/java/de/k3b/android/androFotoFinder/FotoGalleryActivity.java index 736386e3..06632355 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/FotoGalleryActivity.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/FotoGalleryActivity.java @@ -89,9 +89,7 @@ public static void showActivity(String debugContext, Activity context, QueryPara } @Override - protected void onCreate(Bundle savedInstanceState) { - Global.debugMemory(mDebugPrefix, "onCreate"); - super.onCreate(savedInstanceState); + protected void onCreateEx(Bundle savedInstanceState) { final Intent intent = getIntent(); if (BuildConfig.DEBUG) { diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/GalleryFilterActivity.java b/app/src/main/java/de/k3b/android/androFotoFinder/GalleryFilterActivity.java index 2c25ec92..67fdfe21 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/GalleryFilterActivity.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/GalleryFilterActivity.java @@ -139,9 +139,7 @@ public void onSaveInstanceState(Bundle savedInstanceState) { } @Override - protected void onCreate(Bundle savedInstanceState) { - Global.debugMemory(mDebugPrefix, "onCreate"); - super.onCreate(savedInstanceState); + protected void onCreateEx(Bundle savedInstanceState) { final Intent intent = getIntent(); mGalleryFilterPathState = new GalleryFilterPathState().load(this, intent, diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/PhotoAutoprocessingEditActivity.java b/app/src/main/java/de/k3b/android/androFotoFinder/PhotoAutoprocessingEditActivity.java index 71a5fa8a..e5b9a793 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/PhotoAutoprocessingEditActivity.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/PhotoAutoprocessingEditActivity.java @@ -154,10 +154,7 @@ public static PhotoAutoprocessingDto getAutoprocessingData(Intent intent) { } @Override - protected void onCreate(Bundle savedInstanceState) { - Global.debugMemory(mDebugPrefix, "onCreate"); - super.onCreate(savedInstanceState); - + protected void onCreateEx(Bundle savedInstanceState) { this.mLabelGenerator = new AndroidLabelGenerator(getApplicationContext(), "\n"); Intent intent = getIntent(); CharSequence title = (intent == null) ? null : intent.getStringExtra(EXTRA_TITLE); diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/PhotoPropertiesEditActivity.java b/app/src/main/java/de/k3b/android/androFotoFinder/PhotoPropertiesEditActivity.java index 230e1751..13b4447e 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/PhotoPropertiesEditActivity.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/PhotoPropertiesEditActivity.java @@ -173,9 +173,7 @@ public void onSaveInstanceState(Bundle savedInstanceState) { } @Override - protected void onCreate(Bundle savedInstanceState) { - Global.debugMemory(mDebugPrefix, "onCreate"); - super.onCreate(savedInstanceState); + protected void onCreateEx(Bundle savedInstanceState) { setContentView(R.layout.activity_exif_edit); edTitle = (EditText) findViewById(R.id.edit_title); diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/backup/BackupActivity.java b/app/src/main/java/de/k3b/android/androFotoFinder/backup/BackupActivity.java index 0bf0625c..d3c590db 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/backup/BackupActivity.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/backup/BackupActivity.java @@ -200,9 +200,7 @@ private void loadGuiFromData() { } @Override - protected void onCreate(Bundle savedInstanceState) { - Global.debugMemory(mDebugPrefix, "onCreate"); - super.onCreate(savedInstanceState); + protected void onCreateEx(Bundle savedInstanceState) { defineGui(); if (savedInstanceState != null) { diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/imagedetail/ImageDetailActivityViewPager.java b/app/src/main/java/de/k3b/android/androFotoFinder/imagedetail/ImageDetailActivityViewPager.java index 8f244943..3c984152 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/imagedetail/ImageDetailActivityViewPager.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/imagedetail/ImageDetailActivityViewPager.java @@ -241,9 +241,7 @@ public static void showActivity(String debugContext, Activity context, Uri image } @Override - public void onCreate(Bundle savedInstanceState) { - mDebugPrefix = "ImageDetailActivityViewPager#" + (id++) + " "; - Global.debugMemory(mDebugPrefix, "onCreate"); + protected void onCreateEx(Bundle savedInstanceState) { this.mWaitingForMediaScannerResult = false; // #17: let actionbar overlap image so there is no need to resize main view item diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/locationmap/MapGeoPickerActivity.java b/app/src/main/java/de/k3b/android/androFotoFinder/locationmap/MapGeoPickerActivity.java index 4e3d7d0a..272c09a8 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/locationmap/MapGeoPickerActivity.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/locationmap/MapGeoPickerActivity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 by k3b. + * Copyright (c) 2015-2020 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -113,9 +113,7 @@ public static void showActivity(String debugContext, Activity context, SelectedF } @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - + protected void onCreateEx(Bundle savedInstanceState) { SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); Intent intent = this.getIntent(); if (Global.debugEnabled && (intent != null)){ diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/queries/FotoSql.java b/app/src/main/java/de/k3b/android/androFotoFinder/queries/FotoSql.java index 00d0bb90..5fd33e57 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/queries/FotoSql.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/queries/FotoSql.java @@ -62,6 +62,7 @@ * Created by k3b on 04.06.2015. */ public class FotoSql extends FotoSqlBase { + private static boolean firstRun = true; public static final String LOG_TAG = Global.LOG_CONTEXT + "-sql"; public static final int SORT_BY_DATE_OLD = 1; @@ -282,6 +283,10 @@ public class FotoSql extends FotoSqlBase { private static IMediaRepositoryApi mediaDBApi; public static IMediaRepositoryApi getMediaDBApi() { + if ((firstRun) && (FotoSql.mediaDBApi != null)) { + firstRun = false; + FotoSql.deleteMediaWithNullPath(); + } return FotoSql.mediaDBApi; } @@ -1047,12 +1052,14 @@ public static int deleteMediaWithNullPath() { // return deleteMedia("delete without path (_data = null)", context, wherePathIsNull.toAndroidWhere(), null, false); SelectedFiles filesWitoutPath = getSelectedfiles(wherePathIsNull, FotoSql.SQL_COL_PATH, VISIBILITY.PRIVATE_PUBLIC); - String pksAsString = filesWitoutPath.toIdString(); - if ((pksAsString != null) && (pksAsString.length() > 0)) { - QueryParameter whereInIds = new QueryParameter(); - FotoSql.setWhereSelectionPks(whereInIds, pksAsString); + if (filesWitoutPath != null) { + String pksAsString = filesWitoutPath.toIdString(); + if ((pksAsString != null) && (pksAsString.length() > 0)) { + QueryParameter whereInIds = new QueryParameter(); + FotoSql.setWhereSelectionPks(whereInIds, pksAsString); - return mediaDBApi.deleteMedia("delete without path (_data = null)", whereInIds.toAndroidWhere(), null, true); + return mediaDBApi.deleteMedia("delete without path (_data = null)", whereInIds.toAndroidWhere(), null, true); + } } return 0; } diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/queries/MediaContentproviderRepositoryImpl.java b/app/src/main/java/de/k3b/android/androFotoFinder/queries/MediaContentproviderRepositoryImpl.java index 65716b03..28df43ba 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/queries/MediaContentproviderRepositoryImpl.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/queries/MediaContentproviderRepositoryImpl.java @@ -77,11 +77,12 @@ static Cursor createCursorForQuery( excpetion = ex; } finally { if ((excpetion != null) || Global.debugEnabledSql || (out_debugMessage != null)) { + final int count = (query == null) ? 0 : query.getCount(); StringBuilder message = StringUtils.appendMessage(out_debugMessage, excpetion, dbgContext, MODUL_NAME + ".createCursorForQuery:\n", QueryParameter.toString(sqlSelectColums, null, from, sqlWhereStatement, - sqlWhereParameters, sqlSortOrder, query.getCount())); + sqlWhereParameters, sqlSortOrder, count)); if (out_debugMessage == null) { Log.i(LOG_TAG, message.toString(), excpetion); } // else logging is done by caller diff --git a/app/src/main/java/de/k3b/android/widget/FilePermissionActivity.java b/app/src/main/java/de/k3b/android/widget/FilePermissionActivity.java index 5ebed23f..3825a06d 100644 --- a/app/src/main/java/de/k3b/android/widget/FilePermissionActivity.java +++ b/app/src/main/java/de/k3b/android/widget/FilePermissionActivity.java @@ -19,17 +19,68 @@ package de.k3b.android.widget; +import android.Manifest; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.app.ActivityCompat; +import android.util.Log; +import android.widget.Toast; + +import de.k3b.android.androFotoFinder.Common; +import de.k3b.android.androFotoFinder.Global; +import de.k3b.android.androFotoFinder.R; + /** * Manage permission * * write to external-storage and * * write to sdcard/usbstick,.... */ -public abstract class FilePermissionActivity extends PermissionBaseActivity { - private void t() { -/* - super.requestPermisson(Manifest.permission.WRITE_EXTERNAL_STORAGE, - "To %s the app needs write permission.", - (_this, result) -> onSaveChangesWithGrant(_this, result)); -*/ +public abstract class FilePermissionActivity extends ActivityWithAutoCloseDialogs { + + private static final int REQUEST_ID_WRITE_EXTERNAL_STORAGE = 2000; + private static final String PERMISSION_WRITE_EXTERNAL_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN + && ActivityCompat.checkSelfPermission(this, PERMISSION_WRITE_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { + requestPermission(PERMISSION_WRITE_EXTERNAL_STORAGE, REQUEST_ID_WRITE_EXTERNAL_STORAGE); + } else { + onCreateEx(savedInstanceState); + } + } + + protected abstract void onCreateEx(Bundle savedInstanceState); + + /** + * Callback received when a permissions request has been completed. + */ + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + switch (requestCode) { + case REQUEST_ID_WRITE_EXTERNAL_STORAGE: { + final boolean success = (grantResults != null) + && (grantResults.length > 0) + && (grantResults[0] == PackageManager.PERMISSION_GRANTED); + if (success) { + onCreateEx(null); + } else { + Log.i(Global.LOG_CONTEXT, this.getClass().getSimpleName() + + ": " + getText(R.string.permission_error)); + Toast.makeText(this, R.string.permission_error, Toast.LENGTH_LONG).show(); + setResult(Common.RESULT_NO_PERMISSIONS, null); + finish(); + } + return; + } + } + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + } + + protected void requestPermission(final String permission, final int requestCode) { + ActivityCompat.requestPermissions(this, new String[]{permission}, requestCode); } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 59294ec9..ff746f51 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -288,5 +288,7 @@ You can undo hiding by calling the mediascanner from gallery-menu." (Re)Load Media Database + + Missing permisions