首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么用户更改隐私设置时,Android AppOps (隐私管理器)会发送重复事件?

为什么用户更改隐私设置时,Android AppOps (隐私管理器)会发送重复事件?
EN

Stack Overflow用户
提问于 2014-04-30 11:19:21
回答 2查看 997关注 0票数 0

当用户通过AppOps更改他/她的隐私设置(例如,拒绝应用程序访问电话联系人)时,AppOpsManager会向任何监听用户更改内容的人发送消息(例如,包名和操作(例如,读取联系人))。

所以我写了一个监听器来做这件事。然而,我们用户只做了一次更改,我收到了太多重复的事件(例如,用户决定拒绝愤怒的小鸟访问他/她的位置的10个事件),然后应用程序崩溃。

下面是我为每对包和操作注册监听器的代码:

代码语言:javascript
复制
public void startWatchingOperations(AppOpsManager appOps, List<AppOpsManager.PackageOps> opsforapps) {
    SharedPreferences myAppListnerPreferences = getSharedPreferences(APP_OPS_PREFERENCES, Activity.MODE_PRIVATE);
    for (AppOpsManager.PackageOps o:opsforapps) {
        List<OpEntry> opEntry = o.getOps();
        //if I already assigned a listener to this pari of package & operation, then skip 
        if (myAppListnerPreferences.getBoolean(o.getPackageName(), false)==false) {
            for (OpEntry entry:opEntry) {
                //for each pair of package & operation, assign a new listener 
                ChangePrivacySettingsListener opsListner = new ChangePrivacySettingsListener(getApplicationContext());      
                     appOps.startWatchingMode(entry.getOp(),o.getPackageName(),opsListner);
                 }
            myAppListnerPreferences.edit().putBoolean(o.getPackageName(), true).apply();
         }
    }
}

以下是监听程序的一个片段

代码语言:javascript
复制
public class ChangePrivacySettingsListener implements AppOpsManager.Callback {
    public void opChanged(int op, String packageName) {
        AppOpsManager appOps=   (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
        PackageManager pkg = context.getPackageManager();
        try {
                            //this is an object to store the event: package name, 
                            // the operation that has been changed, & time stamp
            PrivacySetting privacySetting = new PrivacySetting();
            privacySetting.setPackageName(packageName);
            privacySetting.setOperation(OPERATIONS_STRINGS[op]);
            privacySetting.setDecisionTime(Calendar.getInstance(TimeZone.getDefault()).getTimeInMillis());
            privacySetting.setUserId(userId);
        } catch (NameNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
     }

Her是AppOpsManager.java的一部分,它允许我监听用户的更改。

代码语言:javascript
复制
public class AppOpsManager {
    final HashMap<Callback, IAppOpsCallback> mModeWatchers
        = new HashMap<Callback, IAppOpsCallback>();

    public void startWatchingMode(int op, String packageName, final Callback callback) {
        synchronized (mModeWatchers) {
          IAppOpsCallback cb = mModeWatchers.get(callback);
          if (cb == null) {
              cb = new IAppOpsCallback.Stub() {
                  public void opChanged(int op, String packageName) {
                      callback.opChanged(op, packageName);
                  }
              };
              mModeWatchers.put(callback, cb);
          }
          try {
              mService.startWatchingMode(op, packageName, cb);
          } catch (RemoteException e) {
          }
   }
}

我仔细检查了一下,以确保我从未为每对包和操作分配超过一个侦听器。

对于潜在原因的提示,我将不胜感激。

Here is a link to AppOpsManager.java

EN

回答 2

Stack Overflow用户

发布于 2014-04-30 12:40:57

尝试将ChangePrivacySettingsListener opsListner的减速移到for块的外侧:

代码语言:javascript
复制
public void startWatchingOperations(AppOpsManager appOps, List<AppOpsManager.PackageOps> opsforapps) {
ChangePrivacySettingsListener opsListner;
SharedPreferences myAppListnerPreferences = getSharedPreferences(APP_OPS_PREFERENCES, Activity.MODE_PRIVATE);
for (AppOpsManager.PackageOps o:opsforapps) {
    List<OpEntry> opEntry = o.getOps();
    //if I already assigned a listener to this pari of package & operation, then skip 
    if (myAppListnerPreferences.getBoolean(o.getPackageName(), false)==false) {
        for (OpEntry entry:opEntry) {
            //for each pair of package & operation, assign a new listener 
             opsListner = new ChangePrivacySettingsListener(getApplicationContext());      
                 appOps.startWatchingMode(entry.getOp(),o.getPackageName(),opsListner);
             }
        myAppListnerPreferences.edit().putBoolean(o.getPackageName(), true).apply();
     }
}

}

请让我知道发生了什么事?

票数 0
EN

Stack Overflow用户

发布于 2018-01-06 22:07:12

如果这对某些人有帮助,至少是Android Oreo,调用AppOpsManager.startWatchingMode(op, packageName, callback)将导致callback在设置更改时被调用(1)对于任何软件包的op (2)对于任何AppOps设置随packageName的更改。这可以从AppOpsService.java源代码中看出,特别是注册回调的AppOpsService.startWatchingMode(),以及当AppOps设置更改时调用回调的AppOpsService.setMode()

例如,如果您使用startWatchingMode(appOps1, package1, callback)startWatchingMode(appOps2, package1, callback)注册回调,当package1appOps3设置发生变化时,该回调将被调用两次,因为您已经注册了两次package1。如果package1appOps1发生变化,回调会被调用三次,因为您已经注册了一次appOps1,两次package1

解决方案是注册您感兴趣的AppOps集(无重复),将packageName参数设置为null,或者注册您感兴趣的包集,将op参数设置为AppOpsManager.OP_NONE

此外,您还需要确保使用stopWatchingMode取消注册所有侦听器(例如,在您活动的onDestroy中)。否则,回调条目将在Activity生命周期中累积(直到应用程序终止),您将开始获得重复项。这也意味着您应该保留对创建的所有侦听器的引用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23379077

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档