小编典典

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

java

我有两个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 在不更改活动的情况下完全可以实现吗?

请帮忙。


阅读 109

收藏
2020-11-01

共1个答案

小编典典

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

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

参考:

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

2020-11-01