Внутреннее средство выбора файлов в Android 4.4 Kitkat

В моем приложении (Keepass2Android) есть внутренний сборщик файлов для поиска баз данных паролей, файлов ключей и т. д. (в основном он был интегрирован для просмотра облачных провайдеров, таких как Dropbox, SkyDrive и т. д.).

Поэтому я добавил разрешение

<permission android:description="@string/permission_desc" android:icon="@drawable/ic_launcher" android:label="KP2A internal file browsing" android:name="keepass2android.keepass2android.permission.KP2aInternalFileBrowsing" android:protectionLevel="signature" />

с android:protectionLevel="signature".

Действие средства выбора файлов помечено android:permission="keepass2android.keepass2android.permission.KP2aInternalFileBrowsing", поэтому мое внутреннее средство выбора файлов не отображается, если другие приложения используют ACTION_GET_CONTENT. (Это было бы неплохо, но это не очень продвинутый сборщик файлов и, конечно же, не основная цель моего приложения для предоставления файлов, поэтому я думаю, что для пользователей было бы довольно неожиданно увидеть мое приложение).

Это прекрасно работает до Android 4.3, но с Android 4.4 это не так: мое приложение по-прежнему отображается в левой части средства выбора файлов Storage Access Framework. Но если пользователи нажмут на нее, это приведет к SecurityException: Permission denied.

    12-16 06:13:33.393 E/AndroidRuntime(16058): java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.GET_CONTENT cat=[android.intent.category.OPENABLE] typ=*/* cmp=keepass2android.keepass2android/group.pals.android.lib.ui.filechooser.FileChooserActivity } from ProcessRecord{42623050 16058:com.android.documentsui/u0a81} (pid=16058, uid=10081) requires keepass2android.keepass2android.permission.KP2aInternalFileBrowsing
12-16 06:13:33.393 E/AndroidRuntime(16058):     at android.os.Parcel.readException(Parcel.java:1465)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at android.os.Parcel.readException(Parcel.java:1419)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2096)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at android.app.Instrumentation.execStartActivity(Instrumentation.java:1419)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at android.app.Activity.startActivityForResult(Activity.java:3424)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at android.app.Activity.startActivityForResult(Activity.java:3385)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at com.android.documentsui.DocumentsActivity.onAppPicked(DocumentsActivity.java:926)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at com.android.documentsui.RootsFragment$2.onItemClick(RootsFragment.java:183)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at android.widget.AdapterView.performItemClick(AdapterView.java:299)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at android.widget.AbsListView.performItemClick(AbsListView.java:1113)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at android.widget.AbsListView$PerformClick.run(AbsListView.java:2904)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at android.widget.AbsListView$3.run(AbsListView.java:3638)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at android.os.Handler.handleCallback(Handler.java:733)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at android.os.Handler.dispatchMessage(Handler.java:95)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at android.os.Looper.loop(Looper.java:136)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at android.app.ActivityThread.main(ActivityThread.java:5017)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at java.lang.reflect.Method.invokeNative(Native Method)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at java.lang.reflect.Method.invoke(Method.java:515)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
12-16 06:13:33.393 E/AndroidRuntime(16058):     at dalvik.system.NativeStart.main(Native Method)
12-16 06:13:33.393 W/ActivityManager(  580):   Force finishing activity com.android.documentsui/.DocumentsActivity
12-16 06:13:33.904 W/ActivityManager(  580): Activity pause timeout for ActivityRecord{42f84718 u0 com.android.documentsui/.DocumentsActivity t42 f}

Я предполагаю, что это происходит потому, что пользовательский интерфейс Storage Access Framework запускается в другом процессе, который не имеет моего разрешения.

Есть ли способ сохранить предполагаемое поведение или мне просто удалить разрешение, чтобы это работало со всеми версиями Android?


person Philipp    schedule 16.12.2013    source источник


Ответы (1)


Если это действие только для внутреннего пользования, просто отключите фильтр намерений.

Теоретически правильным способом избежать того, чтобы внешние приложения знали о ваших компонентах, было бы установить для их экспортируемого свойства значение false из их объявления в файле AndroidManifest.xml.

Однако, как уже поясняет Commonsware, здесь, к сожалению, в стандартном средстве выбора Android есть ошибка, которая будет игнорировать «экспортированный» статус действий при их перечислении, а затем произойдет сбой, если пользователь щелкнет их (похожая ошибка на то, что вы экспериментируете ).

Поэтому, насколько я знаю, лучшее, что вы можете сделать, это просто исключить тег фильтра намерений из объявления активности и вместо этого вызвать его с явным намерением.

person alfongj    schedule 07.05.2015