Merge branch 'usb-otg-nearby-repos' into 'master'

fix repo handling on SDCard/USB-OTG

See merge request fdroid/fdroidclient!950
This commit is contained in:
Hans-Christoph Steiner 2020-11-18 21:57:39 +00:00
commit f4ae1aacc7
9 changed files with 98 additions and 47 deletions

View File

@ -100,7 +100,6 @@
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter"/>
</receiver>
<receiver
android:name=".nearby.UsbDeviceDetachedReceiver">
<intent-filter>
@ -110,6 +109,17 @@
android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"
android:resource="@xml/device_filter"/>
</receiver>
<receiver android:name=".nearby.UsbDeviceMediaMountedReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_EJECT" />
<action android:name="android.intent.action.MEDIA_REMOVED" />
<action android:name="android.intent.action.MEDIA_MOUNTED" />
<action android:name="android.intent.action.MEDIA_BAD_REMOVAL" />
<data android:scheme="content" />
<data android:scheme="file" />
</intent-filter>
</receiver>
<activity
android:name=".panic.PanicPreferencesActivity"

View File

@ -28,11 +28,10 @@ import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Process;
import androidx.core.content.ContextCompat;
import android.util.Log;
import androidx.core.content.ContextCompat;
import org.fdroid.fdroid.IndexUpdater;
import org.fdroid.fdroid.IndexV1Updater;
import org.fdroid.fdroid.Preferences;
import org.fdroid.fdroid.Utils;
import java.io.File;
@ -55,7 +54,7 @@ import java.util.List;
* "External Storage"
* <p>
* Scanning the removable storage requires that the user allowed it. This
* requires both the {@link Preferences#isScanRemovableStorageEnabled()}
* requires both the {@link org.fdroid.fdroid.Preferences#isScanRemovableStorageEnabled()}
* and the {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}
* permission to be enabled.
*
@ -75,11 +74,9 @@ public class SDCardScannerService extends IntentService {
}
public static void scan(Context context) {
if (Preferences.get().isScanRemovableStorageEnabled()) {
Intent intent = new Intent(context, SDCardScannerService.class);
intent.setAction(ACTION_SCAN);
context.startService(intent);
}
Intent intent = new Intent(context, SDCardScannerService.class);
intent.setAction(ACTION_SCAN);
context.startService(intent);
}
@Override

View File

@ -20,7 +20,6 @@
package org.fdroid.fdroid.nearby;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.IntentService;
import android.content.ContentResolver;
import android.content.Context;
@ -28,15 +27,14 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Process;
import androidx.documentfile.provider.DocumentFile;
import android.util.Log;
import android.widget.Toast;
import androidx.documentfile.provider.DocumentFile;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.fdroid.fdroid.AddRepoIntentService;
import org.fdroid.fdroid.IndexUpdater;
import org.fdroid.fdroid.IndexV1Updater;
import org.fdroid.fdroid.Preferences;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.data.Repo;
@ -76,18 +74,21 @@ public class TreeUriScannerIntentService extends IntentService {
public static final String TAG = "TreeUriScannerIntentSer";
private static final String ACTION_SCAN_TREE_URI = "org.fdroid.fdroid.nearby.action.SCAN_TREE_URI";
/**
* @see <a href="https://android.googlesource.com/platform/frameworks/base/+/android-10.0.0_r38/core/java/android/provider/DocumentsContract.java#238">DocumentsContract.EXTERNAL_STORAGE_PROVIDER_AUTHORITY</a>
* @see <a href="https://android.googlesource.com/platform/frameworks/base/+/android-10.0.0_r38/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java#70">ExternalStorageProvider.AUTHORITY</a>
*/
public static final String EXTERNAL_STORAGE_PROVIDER_AUTHORITY = "com.android.externalstorage.documents";
public TreeUriScannerIntentService() {
super("TreeUriScannerIntentService");
}
public static void scan(Context context, Uri data) {
if (Preferences.get().isScanRemovableStorageEnabled()) {
Intent intent = new Intent(context, TreeUriScannerIntentService.class);
intent.setAction(ACTION_SCAN_TREE_URI);
intent.setData(data);
context.startService(intent);
}
Intent intent = new Intent(context, TreeUriScannerIntentService.class);
intent.setAction(ACTION_SCAN_TREE_URI);
intent.setData(data);
context.startService(intent);
}
/**

View File

@ -19,28 +19,21 @@
package org.fdroid.fdroid.nearby;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.UriPermission;
import android.database.ContentObserver;
import android.hardware.usb.UsbManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import android.text.TextUtils;
import android.util.Log;
import org.fdroid.fdroid.views.main.MainActivity;
import androidx.annotation.RequiresApi;
import org.fdroid.fdroid.views.main.NearbyViewBinder;
import java.util.HashMap;
/**
* This is just a shim to receive {@link UsbManager#ACTION_USB_ACCESSORY_ATTACHED}
@ -49,7 +42,6 @@ import java.util.HashMap;
public class UsbDeviceAttachedReceiver extends BroadcastReceiver {
public static final String TAG = "UsbDeviceAttachedReceiv";
private static final HashMap<Uri, ContentObserver> contentObservers = new HashMap<>();
@RequiresApi(api = 19)
@Override
@ -77,6 +69,7 @@ public class UsbDeviceAttachedReceiver extends BroadcastReceiver {
}
};
contentResolver.registerContentObserver(uri, true, contentObserver);
UsbDeviceDetachedReceiver.contentObservers.put(uri, contentObserver);
}
}
}

View File

@ -19,25 +19,17 @@
package org.fdroid.fdroid.nearby;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.UriPermission;
import android.database.ContentObserver;
import android.hardware.usb.UsbManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import android.text.TextUtils;
import android.util.Log;
import org.fdroid.fdroid.views.main.MainActivity;
import androidx.annotation.RequiresApi;
import org.fdroid.fdroid.views.main.NearbyViewBinder;
import java.util.HashMap;
@ -49,7 +41,7 @@ import java.util.HashMap;
public class UsbDeviceDetachedReceiver extends BroadcastReceiver {
public static final String TAG = "UsbDeviceDetachedReceiv";
private static final HashMap<Uri, ContentObserver> contentObservers = new HashMap<>();
static final HashMap<Uri, ContentObserver> contentObservers = new HashMap<>();
@RequiresApi(api = 19)
@Override

View File

@ -0,0 +1,23 @@
package org.fdroid.fdroid.nearby;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Environment;
import org.fdroid.fdroid.views.main.NearbyViewBinder;
public class UsbDeviceMediaMountedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent == null || intent.getAction() == null) {
return;
}
String action = intent.getAction();
if (Environment.MEDIA_BAD_REMOVAL.equals(action)
|| Environment.MEDIA_MOUNTED.equals(action)
|| Environment.MEDIA_REMOVED.equals(action)
|| Environment.MEDIA_EJECTING.equals(action)) {
NearbyViewBinder.updateUsbOtg(context);
}
}
}

View File

@ -13,6 +13,7 @@ import android.os.Build;
import android.os.Environment;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.provider.DocumentsContract;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
@ -21,11 +22,9 @@ import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.nearby.SDCardScannerService;
@ -61,6 +60,8 @@ import java.util.List;
*
* @see TreeUriScannerIntentService
* @see org.fdroid.fdroid.nearby.SDCardScannerService
* <p>
* TODO use {@link StorageManager#registerStorageVolumeCallback(Executor, StorageManager.StorageVolumeCallback)}
*/
public class NearbyViewBinder {
public static final String TAG = "NearbyViewBinder";
@ -165,11 +166,26 @@ public class NearbyViewBinder {
for (final StorageVolume storageVolume : storageManager.getStorageVolumes()) {
if (storageVolume.isRemovable() && !storageVolume.isPrimary()) {
Log.i(TAG, "StorageVolume: " + storageVolume);
final Intent intent = storageVolume.createAccessIntent(null);
if (intent == null) {
Intent tmpIntent = null;
if (Build.VERSION.SDK_INT < 29) {
tmpIntent = storageVolume.createAccessIntent(null);
} else {
tmpIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
tmpIntent.putExtra(DocumentsContract.EXTRA_INITIAL_URI,
Uri.parse("content://"
+ TreeUriScannerIntentService.EXTERNAL_STORAGE_PROVIDER_AUTHORITY
+ "/tree/"
+ storageVolume.getUuid()
+ "%3A/document/"
+ storageVolume.getUuid()
+ "%3A"));
}
if (tmpIntent == null) {
Utils.debugLog(TAG, "Got null Storage Volume access Intent");
return;
}
final Intent intent = tmpIntent;
storageVolumeText.setVisibility(View.VISIBLE);
String text = storageVolume.getDescription(context);
@ -196,8 +212,23 @@ public class NearbyViewBinder {
return;
}
}
((Activity) context).startActivityForResult(intent,
MainActivity.REQUEST_STORAGE_ACCESS);
Activity activity = null;
if (context instanceof Activity) {
activity = (Activity) context;
} else if (swapView != null && swapView.getContext() instanceof Activity) {
activity = (Activity) swapView.getContext();
}
if (activity != null) {
activity.startActivityForResult(intent, MainActivity.REQUEST_STORAGE_ACCESS);
} else {
// scan in the background without requesting permissions
Toast.makeText(context.getApplicationContext(),
context.getString(R.string.scan_removable_storage_toast, externalStorage),
Toast.LENGTH_SHORT).show();
SDCardScannerService.scan(context);
}
}
});
}

View File

@ -539,7 +539,9 @@ public class FDroidApp extends Application {
atStartTime.edit().remove(queryStringKey).apply();
}
SDCardScannerService.scan(this);
if (Preferences.get().isScanRemovableStorageEnabled()) {
SDCardScannerService.scan(this);
}
}
/**

View File

@ -21,14 +21,14 @@
package org.fdroid.fdroid.views.main;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;
import android.util.SparseIntArray;
import android.view.Menu;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.PopupMenu;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;
import org.fdroid.fdroid.R;
/**
@ -76,6 +76,8 @@ class MainViewAdapter extends RecyclerView.Adapter<MainViewController> {
long viewType = getItemId(holder.getAdapterPosition());
if (viewType == R.id.updates) {
holder.bindUpdates();
} else if (viewType == R.id.nearby) {
NearbyViewBinder.updateUsbOtg(activity);
}
}