Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Android AppOps(隐私管理器)在用户更改其隐私设置时发送重复事件?_Android_Listener - Fatal编程技术网

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

为什么Android AppOps(隐私管理器)在用户更改其隐私设置时发送重复事件?,android,listener,Android,Listener,当用户通过AppOps更改其隐私设置(例如,拒绝应用程序访问电话联系人)时,AppOpsManager会将用户更改的内容(例如程序包名称和操作(例如,读取联系人))发送给任何人 所以我写了一个听众来这样做。但是,我们用户只做了一次更改,我收到了太多重复事件(例如,用户决定拒绝愤怒的小鸟访问他/她的位置的10个事件),然后应用程序崩溃 下面是我为每对包和操作注册listners的代码: public void startWatchingOperations(AppOpsManager appOps

当用户通过AppOps更改其隐私设置(例如,拒绝应用程序访问电话联系人)时,AppOpsManager会将用户更改的内容(例如程序包名称和操作(例如,读取联系人))发送给任何人

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

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

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();
         }
    }
}
她是apppsmanager.java的一部分,允许我监听用户的更改

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) {
          }
   }
}
公共类AppOpsManager{
最终哈希映射
=新HashMap();
public void startWatchingMode(int-op、字符串packageName、最终回调){
已同步(MMO脱水器){
IAppOpsCallback cb=mModeWatchers.get(回调);
如果(cb==null){
cb=新的IAppOpsCallback.Stub(){
public void opChanged(int-op,String-packageName){
opChanged(op,packageName);
}
};
mModeWatchers.put(回调,cb);
}
试一试{
mService.startWatchingMode(op、packageName、cb);
}捕获(远程异常){
}
}
}
我仔细检查以确保从未为每对包和操作分配过多个侦听器

我希望得到关于潜在原因的提示


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

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();
     }
}
public void startWatchingOperations(AppOpsManager appOps,List opsforapps){
更改PrivacySettingsListener OpsListener;
SharedReferences myAppListnerPreferences=GetSharedReferences(应用程序操作首选项,活动模式\私有);
对于(AppOpsManager.PackageOps o:OpsFrapps){
List opEntry=o.getOps();
//如果我已经为这个部分的包和操作分配了一个侦听器,那么跳过
if(myAppListnerPreferences.getBoolean(o.getPackageName(),false)==false){
for(OpEntry条目:OpEntry){
//对于每对包和操作,分配一个新的侦听器
opsListner=newchangePrivacySettingsListener(getApplicationContext());
appOps.startWatchingMode(entry.getOp()、o.getPackageName()、opsListner);
}
myAppListnerPreferences.edit().putBoolean(o.getPackageName(),true.apply();
}
}
}


请告诉我发生了什么事?

以防万一,这对某些人(至少是Android Oreo)调用AppsManager会有帮助。startWatchingMode(op,packageName,callback)将导致在更改任何包的
op
的设置时调用
回调
(1)和(2)对于任何AppOps设置更改,请使用
packageName
。这可以从
AppOpsService.java
源代码中看到,尤其是注册回调的
AppOpsService.startWatchingMode()
,它在AppOps设置更改时调用回调

例如,如果使用
startWatchingMode(appOps1,package1,callback)
startWatchingMode(appOps2,package1,callback)
注册回调, 当
package1
appOps3
设置发生更改时,回调将被调用两次,因为您已为
package1
注册了两次。如果
appOps1
package1
更改,回调将被调用三次,因为您已为
appOps1注册了一次,两次用于
程序包1

解决方案是使用
packageName
参数设置为
null
注册您感兴趣的appop集(无重复),或者使用
op
参数设置为
AppOpsManager.op\u NONE
注册您感兴趣的包集


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

谢谢@BasemAljedai。它解决了一半问题。应用程序不再崩溃。但是,当用户更改其设置时,我仍然会收到副本。我原以为声明的位置并不重要,但显然我错了。
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();
     }
}