当前位置: 首页 > 面试题库 >

全局类为Android中的所有活动注册侦听器

卫飞鹏
2023-03-14
问题内容

我有两个Activity类。Activity AActivity B。稍后,我添加Activity C了当用户摇动设备在Activity A或时启动的功能Activity B。现在,如果我在Activity A和中注册了ShakeListener Acitivity B,就可以实现我的目标

但是,我现在想要的是另一回事,我不想更改Activity AActivity B。我想编写一个不同的类,该类在整个应用程序中运行,并为该应用程序中的所有活动注册ShakeListener。我怎样才能做到这一点?那应该是什么样的课?

我尝试了扩展BroadcastReceiver并在onReceive方法中注册了ShakeListener,但使用了BOOT_EVENT,它仅在设备启动而不是应用程序启动时才被触发。因此无法实现我的目标。

然后,一个SO用户建议我扩展Application类并在那里注册侦听器。现在,侦听器已注册,但现在我需要将当前正在运行的Activity和上下文传递给Activity C。在这里,我又回到了零,因为我不想在活动A或B中添加代码。此外,AFAIK,在启动任何活动之前调用Application类,因此有可能获取当前在前台运行Activity?

然后,我想到了移动代码以在侦听器本身中找到活动。在这里,我还需要获取当前的活动和上下文。上下文是应用程序上下文,然后我尝试在此线程之后访问所有当前打开的活动。根据版本,代码有所不同。这不是推荐的方法,并且给我错误。

这是课程:

package com.something.someotherthing;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.os.Build;
import android.util.Log;    
import java.lang.reflect.Field;
import java.util.List;

/**
 * Created by  Inquisitive on 20/5/15.
 */
public class ShakeEventListener implements SensorEventListener {

    private Context context;
    private Activity activity;


    private String[] getPreLollipop() {
        try {
               @SuppressWarnings("deprecation")
            List<ActivityManager.RunningTaskInfo> tasks =
                    activityManager().getRunningTasks(1);
            ActivityManager.RunningTaskInfo currentTask = tasks.get(0);
            ComponentName currentActivity = currentTask.topActivity;
            return new String[]{currentActivity.getClassName()};
        }
        catch(Exception e){
            Log.d("version","Exception" +e.getClass());
            String str[]= {"abc","def"};
            return str;
        }
    }

    private String[] getLollipop() {
        final int PROCESS_STATE_TOP = 2;

        try {
            Field processStateField = ActivityManager.RunningAppProcessInfo.class.getDeclaredField("processState");

            List<ActivityManager.RunningAppProcessInfo> processes =
                    activityManager().getRunningAppProcesses();
            for (ActivityManager.RunningAppProcessInfo process : processes) {
                if (
                    // Filters out most non-activity processes
                        process.importance <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
                                &&
                                // Filters out processes that are just being
                                // _used_ by the process with the activity
                                process.importanceReasonCode == 0
                        ) {
                    int state = processStateField.getInt(process);

                    if (state == PROCESS_STATE_TOP)
                    /*
                    If multiple candidate processes can get here,
                            it's most likely that apps are being switched.
                    The first one provided by the OS seems to be
                    the one being switched to, so we stop here.
                            */
                        return process.pkgList;
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return new String[] { };
    }

    private ActivityManager activityManager() {
        return (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    }


    public String[] get() {
        if (Build.VERSION.SDK_INT < 21) {
            Log.d("Version","Pre-lollipop");
            for(String str:getPreLollipop())
                Log.d("Version",str);
            return getPreLollipop();
        }
        else {
            Log.d("Version","Lollipop");
            for(String str:getLollipop())
                Log.d("Version",str);
            return getLollipop();
        }
    }
    public ShakeEventListener(Context context){
        Log.d("ACCELEROMETER","inside the constructor of shake event listener");
        this.context=context;
        String str[] = get();
        try {
            Class<?> myClass = Class.forName(str[0]);
            activity = (Activity) myClass.newInstance();
        }catch(Exception  e){
            //do something
        }

    }
    public void onAccuracyChanged(Sensor sensor, int accuracy){

    }
    public void onSensorChanged(SensorEvent se){
        Log.d("SENSOR","On sensor changed");

      //need the activity and context here..
    }


}

当我尝试使用棒棒糖以下版本的设备时。它捕获了SecurityException。对于具有棒棒糖以上版本的设备,它会给出我的应用程序的程序包名称,但不会给出特定的类。

1 实现目标的正确方法是什么?无论我采用哪种方法都是正确的?在这种情况下,我将尝试调试代码以查找活动

2 如果没有,我还有哪些其他选择可以实现我的目标,即拥有一个可以监听应用程序中任何活动的全局监听器。

3 在不更改活动的情况下完全可以实现吗?

请帮忙。


问题答案:

对于您的情况,您需要实现一个服务以在后台监听传感器。浏览文档:服务

您不能仅使用Broadcastreceiver来完成此任务。

参考:

请参阅此链接以获取帮助:http :
//code.tutsplus.com/tutorials/android-barometer-logger-acquiring-sensor-data
–mobile-10558



 类似资料:
  • 我最近发现自己正在编写以下代码: 一位同事指出 然而, 基于这一点,我得到的印象是我没有正确理解,我开始怀疑我的原始代码是否安全。 DR 使用引用要用作侦听器且需要多次引用的方法(例如,添加+删除)是否安全? 关于匿名类等的幕后实际发生了什么?

  • 我尝试将在Apache Camel处理器中处理的数据推送到侦听器类。在处理器类实例中,我尝试在Camel上下文的实例化期间注册侦听器,但不知何故失败了。也许我在这里根本错误,这是不可能的。如果是这种情况,最好你告诉我。 我有一个Apache Camel路由,从ActiveMQ服务器获取JSON消息,并将这些JSON推送到一个自定义处理器类,该类由Camel-Spring XML定义: 我的想法是,

  • 我有jbpm系统(),我想在系统内使用一个全局的。我创建了简单的过程事件lestener: 我的pom。xml: 当我将其添加为部署依赖项并通过工作台将其声明为jbpm项目中的事件监听器时,一切都运行正常。 但是现在我有很多项目,把事件监听器附加到每个项目上很不舒服。因此,我在wildfly中创建了新模块: 已创建部署描述符。xml服务器级别: 因此,当我创建一个新的jbpm进程并通过工作台将其部

  • 注意: 自 PHP 5.4.0 开始,register_globals 选项已经被移除并不再使用。这是在提醒你如果你正在升级旧的应用程序的话,你需要注意这一点。 当 register_globals 选项被开启时,它会使许多类型的变量(包括 $_POST, $_GET 和 $_REQUEST)被注册为全局变量。这将很容易使你的程序无法有效地判断数据的来源并导致安全问题。 例如:$_GET['foo

  • EasySwoole有四个全局事件,全部位于框架安装后生成的EasySwooleEvent.php中。 frameInitialize 框架初始化事件 mainServerCreate 主服务创建事件 onRequest Http请求事件 afterAction Http响应后事件 frameInitialize mainServerCreate onRequest afterAction

  • 一旦中的所有元素都为真,我想隐藏。为此,我使用。现在立即消失,似乎无需等待所有true。这是我的代码。 左抽屉指针: RestModel: 怎么解决?