简体   繁体   English

Android 6 Permissions =>禁用权限时崩溃并返回应用程序

[英]Android 6 Permissions => Crash when disable permission and go back to the app

I would like to use permission for android 6 in my app but i saw a strange event. 我想在我的应用程序中使用android 6的权限,但我看到一个奇怪的事件。 Perhaps you can help me about that. 也许你可以帮助我。

If you start your app with "Dangerous" permissions, these permissions appears in the "App permissions" of your android device. 如果您使用“危险”权限启动应用程序,这些权限将显示在Android设备的“应用程序权限”中。 PERFECT! 完善!

BUT if you keep your app in background, go to the "App permissions" menu, disable (you can enable and then disable it) a permission and go back to your app, android never go to onStart (Fragment or activity) ?! 但是如果您将应用程序保留在后台,请转到“应用程序权限”菜单,禁用(您可以启用然后禁用它)权限并返回到您的应用程序,android永远不会进入onStart(片段或活动)? And never go there again. 永远不要再去那里了。

If you don't touch to the permission or if you enable a permission => it go to onStart and others. 如果您未触及权限,或者您启用了权限=>,则转到onStart和其他人。

That's problematic, for exemple, if your app use listeners, you can't restart it and you can have a crash... 这是有问题的,例如,如果您的应用程序使用侦听器,您无法重新启动它,您可能会崩溃...

Do you know the method where Android go when you disable a permission ? 您是否知道Android禁用权限时的方法?

I tried onCreate onStart onResume onRestart onRestoreInstanceState onActionModeStarted onRestoreInstanceState onPostResume onContentChanged 我尝试onCreate onStart onResume onRestart onRestoreInstanceState onActionModeStarted onRestoreInstanceState onPostResume onContentChanged

... but no way... :/ ......但是没办法......:/

Here is my solution: 这是我的解决方案:

I use some fragments in my mainActivity. 我在mainActivity中使用了一些片段。

As you know, the activity is recreated when user disable a permission => go through onCreate, ... 如您所知,当用户禁用权限=>通过onCreate时,将重新创建活动,...

What i do in the onCreate(...) of my mainActivity, i remove all loaded fragments and put my app in the same state as a first run. 我在mainActivity的onCreate(...)中做了什么,我删除了所有加载的片段,并将我的应用程序置于与第一次运行相同的状态。

Like this: 像这样:

    // Clean fragments (only if the app is recreated (When user disable permission))
    FragmentManager fragmentManager = getSupportFragmentManager();
    if (fragmentManager.getBackStackEntryCount() > 0) {
        fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }

    // Remove previous fragments (case of the app was restarted after changed permission on android 6 and higher)
    List<Fragment> fragmentList = fragmentManager.getFragments();
    if (fragmentList != null) {
        for (Fragment fragment : fragmentList) {
            if (fragment != null) {
                fragmentManager.beginTransaction().remove(fragment).commit();
            }
        }
    }

Be careful !!! 小心 !!! : I had a crash with the version 23.2.0 of appcompat and design libraries. :我的appcompat和设计库版本23.2.0崩溃了。 This crash appear when the app is recreated ! 重新创建应用程序时会出现此崩溃!

Check this link for more info. 请查看此链接以获取更多信息。

As already pointed out correct android is relaunching your app. 正如已经指出的那样,正确的android正在重启你的应用程序。 This is the same behavior as when your app is in background and the system kills your application as more memory is used. 这与您的应用程序处于后台时的行为相同,并且系统会在使用更多内存时杀死您的应用程序。 What happens when you go back to your application is that the last activity inclusiv fragment(s) is recreated. 返回应用程序时会发生的情况是重新创建最后一个包含片段的活动。

Usually a start up screen (splash screen) is used to initialize the application. 通常使用启动屏幕(启动屏幕)来初始化应用程序。 Once the application is initialize (for example the services, viewmodel are ready) the startup-activity is switched to the main activity. 初始化应用程序后(例如,服务,viewmodel已准备好),启动活动将切换到主活动。

A common crash occurs in many applications when the app is recreated(for example revoke permissions) as the app is not initialized and the services or viewmodels are used which are null. 在重新创建应用程序时,许多应用程序中都会发生常见崩溃(例如撤销权限),因为应用程序未初始化且使用的服务或视图模型为空。 I don't think there is a way to avoid a recreation of the last activity after a app restart. 我认为有一种方法可以避免在重新启动应用程序后重新创建上一个活动。

What you could do is to check if the application is initialized and otherwise switch to the startup activity and initialize the app. 您可以做的是检查应用程序是否已初始化,否则切换到启动活动并初始化应用程序。 Be aware that you have to handle unitialized applications in the activity and also the fragments. 请注意,您必须处理活动中的单元化应用程序以及片段。

Xamarin example code: Xamarin示例代码:

if (!((MyApplication)ApplicationContext).IsInitialized)
{
    Intent intent = new Intent(Application.Context,typeof(StartupActivity));
    intent.SetFlags(ActivityFlags.NewTask);
    StartActivity(intent);
    Finish();
}

As soon as base.onCreate is called the fragments are created so even the provided "workaround" from acs-team does not avoid the recreation of the last fragment. 一旦调用了base.onCreate,就会创建片段,因此即使是acs-team提供的“解决方法”也无法避免重新创建最后一个片段。

With the above provided sample code the lifecycle will be in case the activity had a fragment: 使用上面提供的示例代码,生命周期将在活动具有片段的情况下:

  • Revoke permission app gets killed 撤销权限应用程序被杀死
  • Restart app 重启应用
  • Application OnCreate 应用程序OnCreate
  • LastActivity.OnCreate LastActivity.OnCreate
  • LastFragment.OnAttach LastFragment.OnAttach
  • LastFragment.OnCreate LastFragment.OnCreate
  • LastFragment.OnCreateView LastFragment.OnCreateView
  • LastFragment.OnViewCreated LastFragment.OnViewCreated
  • LastFragment.OnDestroy LastFragment.OnDestroy
  • LastFragment.OnDettach LastFragment.OnDettach
  • LastActivity.OnDestroy LastActivity.OnDestroy
  • StartupActivity.OnCreate StartupActivity.OnCreate

By the way you can also test an app restart over the adb shell: 顺便说一句,您还可以通过adb shell测试应用重启:

Open your app then go to the android home screen in order that your app is in the background 打开您的应用程序,然后转到Android主屏幕,以便您的应用程序在后台

adb shell "ps | grep <com.yourpackage>" // get the app process id
adb shell run-as <com.yourpackage> kill <app-process-id>    // kill the app

start the your app again over the icon or the recent tasks 通过图标或最近的任务再次启动您的应用程序

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM