隐私权限弹框的使用说明

监管部门要求在用户点击隐私协议弹框中 同意 按钮之前,App 不可以调用相关敏感 API。为应对此监管要求,mPaaS Android 10.1.32.17 以上(32 版本) 和 10.1.60.5 以上(60 版本)的基线提供了支持。如果您采用的是组件化的接入方法,请您根据实际情况参考本文对工程进行改造。

使用方法

重要

弹出隐私弹框的 Activity 不可以继承 mPaaS 的 BaseActivity,因为 BaseActivity 会进行埋点数据采集,会导致 App 在同意隐私政策之前采集隐私数据。

  1. 新建隐私许可弹框回调类。在代码中新建一个类,实现 PrivacyListener 接口,类的实现可以参考以下代码:

    public class MyPrivacyListener implements PrivacyListener {
     // 在本方法内进行隐私许可弹框
     @Override
     public void showPrivacy(final Activity activity, final PrivacyResultCallback privacyResultCallback) {
         if(null==privacyResultCallback){
            return;
         }
         if(null!=activity){
             new AlertDialog.Builder(activity)
                     .setTitle("隐私许可弹框")
                     .setMessage("主体内容")
                     .setPositiveButton("同意继续使用", new DialogInterface.OnClickListener() {
                         @Override
                         public void onClick(DialogInterface dialogInterface, int i) {
                             // 点击确定后,取消弹框
                             dialogInterface.cancel();
                             // 将弹框结果设置为 true
                             privacyResultCallback.onResult(true);
                         }
                     })
                     .setNegativeButton("不同意并退出", new DialogInterface.OnClickListener() {
                         @Override
                         public void onClick(DialogInterface dialogInterface, int i) {
                             // 点击不同意后,取消弹框
                             dialogInterface.cancel();
                             // 将弹框结果设置为 false
                             privacyResultCallback.onResult(false);
                             // 结束掉当前的 activity,框架会杀掉进程
                             if(null!=activity){
                                 activity.finish();
                             }
                         }
                     })
                     .setCancelable(false)
                     .create()
                     .show();
         }else{
             // 如果 activity 是空的话,回调结果设置 false
             privacyResultCallback.onResult(false);
         }
     }
    }
    说明

    如果您使用的是 10.1.68.42 及以上版本基线且需要清除隐私状态,请实现 PrivacyListener2 接口,并实现 shouldClear 函数。

    以下代码是对 shouldClear 函数的说明:

    @Override
    public boolean shouldClear(Context context) {
      //用户没有点同意隐私协议默认用 SharedPreferences 存储 false 设置为 return false。如果需要再次弹窗需 SP 存储 true 设置为return true;
      return false;//return 的值取 SP 里面存的 boolean 值。
    }

    回调时,一定要弹出一个对话框来触发 windowFocusChange,触发后框架才会进行后续的操作。由于该回调类会由系统框架进行反射初始化,且时机非常早,因此请不要添加带方法名的构造函数,以及在构造函数中加入具体逻辑。

    如果您需要在弹出对话框这里使用资源,在不同基线下需要采用不同的方法。

    • 在 32 基线下,您需要采用如下方法:Resources resource = QuinoxAgent.getInstance().getResourcesByBundle("资源所在的bundle的bundlename");

      说明

      bundlename 可在 Bundle 工程中的主 module 中的 /build/intermediates/bundle/META-INF/BUNDLE.MF 中查看。

      bundlename
    • 在 60 基线下,您需要在 Portal 工程的主 module 下,建立 res_slinks 文件,并将您的资源所在的 bundle 的 groupartifact 按照规则写到 res_slinks 文件内。规则为 group-artifact.split("-")[0]。如果组合后内容过长需要换行,请您注意进行换行处理。例如:group = com.mpaas.demo.materialdesignartifact = materialdesign-build,最终写入 res_slinks 文件中的配置是 com.mpaas.demo.materialdesign-materialdesign1

      完成以上内容后,您可以直接使用 LayoutInflator.inflate(R.layout.xxx) 来调用资源。

  2. AndroidManifest 中注册弹框回调类。在 portalAndroidManifest 中注册隐私许可弹框回调类,value 是刚才实现的隐私许可弹框回调类的全路径。代码如下所示。注意将全路径及类名要替换成您自己的回调类。

    <!--隐私许可弹框回调-->
    <meta-data
     android:name="privacy.listener"
     android:value="com.mpaas.demo.launcher.MyPrivacyListener" />
  3. 启动弹框拦截。在 MockLauncherApplicationAgentpreInit 中,加入启动弹框拦截。代码如下所示:

    //检测是否要向用户进行隐私许可弹框
    if(!PrivacyUtil.isUserAgreed(getApplicationContext())){
     PermissionGate.getInstance().waitForUserConform(mContext, getMicroApplicationContext());
    }
  4. 启动第一个 Activity。在 MockLauncherActivityAgentpostInit 中,进行第一个 Activity 的跳转。代码如下所示:

    public class MockLauncherActivityAgent extends LauncherActivityAgent {
        
        private Handler mUIHandler = new Handler(Looper.getMainLooper());
        
        @Override
        public void preInit(Activity activity) {
            super.preInit(activity);
        }
    
        @Override
        public void postInit(final Activity activity) {
            super.postInit(activity);
    
            if (PrivacyUtil.isUserAgreed(activity)) {
                mUIHandler.postDelayed(new Runnable() {
                    public void run() {
                        Intent intent = new Intent(activity, MainActivity.class);
                        activity.startActivity(intent);
                        activity.finish();
                    }
                }, 1000);
            } else {
    
                PermissionGate.getInstance().registerPrivacyCallback(
                        new PrivacyCallback() {
                            @Override
                            public void onTermsOfUseAgreed() {
                                mUIHandler.postDelayed(new Runnable() {
                                    public void run() {
                                        Intent intent = new Intent(activity, MainActivity.class);
                                        activity.startActivity(intent);
                                        activity.finish();
                                    }
                                }, 1000);
                            }
                        }
                );
            }
        }
    
    }