如何在 Android 中使用后台服务覆盖两次甚至 3 次单击电源按钮甚至音量增大/减小键?

Nia*_*shi 1 java service android

我正在开发一个应用程序,我可以在 3-5 秒内听到连续点击POWER_BUTTON 3 次的声音。

我已经在 StackOverflow 上搜索了所有答案,但没有一个对我有用。

Lars D的这个答案应该适用于该活动,但尽管已被接受,但也不起作用。

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_POWER) {
        Intent i = new Intent(this, ActivitySetupMenu.class);
        startActivity(i);
        return true;
    }

    return super.dispatchKeyEvent(event);
}
Run Code Online (Sandbox Code Playgroud)

有一个应用程序打算执行此操作,我安装了它,但它仍然不起作用,也许他们使用的 API 已贬值甚至已被删除。

这些解决方案不起作用的原因

  1. 当应用程序被杀死/摧毁并且不再检测到时。
  2. 屏幕被锁定,并且不再检测到。
  3. 可能是SDK不支持。

也许我们可以找到一种方法来在活动上执行此操作,但我想在应用程序被终止/在后台/屏幕锁定时/屏幕关闭时使用服务/广播接收器监听操作。

好吧,这个问题在 StackOverflow 上肯定重复了很多次,但没有给出完整或有效的答案。

Nia*_*shi 5

由于没有人试图解决这个问题,或者甚至可能无法理解这个问题,幸运的是,经过几个小时的网络搜索后,我发现了这个很棒的网站,它完全解决了我的问题,并且也想将其发布在这里。

\n

现在解决的问题:

\n
    \n
  1. 我的应用程序始终在后台运行,即使它被杀死/销毁或从系统托盘中删除。
  2. \n
  3. 单击时该服务始终侦听 POWER_BUTTON。
  4. \n
  5. SDK 支持这一点,因为它仅使用广播接收器和服务。
  6. \n
\n

我只是写下步骤,以防链接将来可能不起作用或被删除:

\n

1.首先我们将创建一个广播接收器,它可以监听并处理 Android 屏幕开/关广播事件,如下所示。

\n

ScreenOnOffReceiver.java

\n
import android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.util.Log;\n\npublic class ScreenOnOffReceiver extends BroadcastReceiver {\n\nprivate final static String SCREEN_TOGGLE_TAG = "SCREEN_TOGGLE_TAG";\n\n@Override\npublic void onReceive(Context context, Intent intent) {\n    String action = intent.getAction();\n    if(Intent.ACTION_SCREEN_OFF.equals(action))\n    {\n        Log.d(SCREEN_TOGGLE_TAG, "Screen is turn off.");\n    }else if(Intent.ACTION_SCREEN_ON.equals(action))\n    {\n        Log.d(SCREEN_TOGGLE_TAG, "Screen is turn on.");\n    }}\n}\n
Run Code Online (Sandbox Code Playgroud)\n

2. 在Activity中注册和注销ScreenOnOffReceiver。

\n

现在我们将创建一个 Activity 并在 it\xe2\x80\x99s 的 onCreate() 方法中注册 ScreenOnOffReceiver,并在 it\xe2\x80\x99s 的 onDestroy() 方法中注销接收器,如下所示。

\n

ScreenOnOffActivity.java

\n
import android.content.IntentFilter;\nimport android.os.Bundle;\nimport android.support.v7.app.AppCompatActivity;\nimport android.util.Log;\n\nimport com.dev2qa.example.R;\nimport com.dev2qa.example.broadcast.receiver.ScreenOnOffReceiver;\n\npublic class ScreenOnOffActivity extends AppCompatActivity {\n\n    private ScreenOnOffReceiver screenOnOffReceiver = null;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_screen_on_off);\n\n        setTitle("dev2qa.com - Keep BroadcastReceiver Running After App Exit.");\n\n        // Create an IntentFilter instance.\n        IntentFilter intentFilter = new IntentFilter();\n\n        // Add network connectivity change action.\n        intentFilter.addAction("android.intent.action.SCREEN_ON");\n        intentFilter.addAction("android.intent.action.SCREEN_OFF");\n\n        // Set broadcast receiver priority.\n        intentFilter.setPriority(100);\n\n        // Create a network change broadcast receiver.\n        screenOnOffReceiver = new ScreenOnOffReceiver();\n\n        // Register the broadcast receiver with the intent filter object.\n        registerReceiver(screenOnOffReceiver, intentFilter);\n\n        Log.d(ScreenOnOffReceiver.SCREEN_TOGGLE_TAG, "onCreate: screenOnOffReceiver is registered.");\n\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n\n        // Unregister screenOnOffReceiver when destroy.\n        if(screenOnOffReceiver!=null)\n        {\n            unregisterReceiver(screenOnOffReceiver);\n            Log.d(ScreenOnOffReceiver.SCREEN_TOGGLE_TAG, "onDestroy: screenOnOffReceiver is unregistered.");\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在以下步骤中运行上述活动。

\n
    \n
  1. 启动活动,有一条日志消息表明广播接收器已在 Activity\xe2\x80\x99s onCreate() 方法中注册。
  2. \n
  3. 按电源按钮关闭屏幕。
  4. \n
  5. 再次按下电源按钮即可打开屏幕。
  6. \n
  7. 您可以在 Android 监控控制台中查看上述步骤的日志数据。
  8. \n
  9. 键入后退菜单以退出活动。您还可以在 Activity\xe2\x80\x99s onDestroy() 方法中看到广播接收器未注册。
  10. \n
  11. 按电源按钮再次执行步骤2、3,但android监控控制台中没有打印任何日志数据。
  12. \n
\n

跑步活动

\n

3. Android后台服务中注册和注销广播接收器

\n

当你在activity中注册广播接收器时,它会在activity退出后停止。

\n

为了解决这个问题,我们将创建一个android服务对象,并在服务对象中注册和注销广播接收器。

\n

因为在 Activity 退出后,Android 服务对象仍会在后台运行,所以在 Android 应用程序退出后,广播接收器仍将运行。

\n

3.1 创建Android服务类。

\n

3.1.1 创建一个扩展 android.app.Service 的 Java 类。

\n

ScreenOnOffBackgroundService.java

\n
import android.app.Service;\nimport android.content.Intent;\nimport android.content.IntentFilter;\nimport android.os.IBinder;\nimport android.support.annotation.Nullable;\nimport android.util.Log;\n\nimport ScreenOnOffReceiver;\n\npublic class ScreenOnOffBackgroundService extends Service {\n\n    private ScreenOnOffReceiver screenOnOffReceiver = null;\n\n    @Nullable\n    @Override\n    public IBinder onBind(Intent intent) {\n        return null;\n    }\n\n    @Override\n    public int onStartCommand(Intent intent, int flags, int startId) {\n        return super.onStartCommand(intent, flags, startId);\n    }\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n\n        // Create an IntentFilter instance.\n        IntentFilter intentFilter = new IntentFilter();\n\n        // Add network connectivity change action.\n        intentFilter.addAction("android.intent.action.SCREEN_ON");\n        intentFilter.addAction("android.intent.action.SCREEN_OFF");\n\n        // Set broadcast receiver priority.\n        intentFilter.setPriority(100);\n\n        // Create a network change broadcast receiver.\n        screenOnOffReceiver = new ScreenOnOffReceiver();\n\n        // Register the broadcast receiver with the intent filter object.\n        registerReceiver(screenOnOffReceiver, intentFilter);\n\n        Log.d(ScreenOnOffReceiver.SCREEN_TOGGLE_TAG, "Service onCreate: screenOnOffReceiver is registered.");\n    }\n\n    @Override\n    public void onDestroy() {\n        super.onDestroy();\n\n        // Unregister screenOnOffReceiver when destroy.\n        if(screenOnOffReceiver!=null)\n        {\n            unregisterReceiver(screenOnOffReceiver);\n            Log.d(ScreenOnOffReceiver.SCREEN_TOGGLE_TAG, "Service onDestroy: screenOnOffReceiver is unregistered.");\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

3.1.2 在AndroidManifest.xml文件中添加Service Xml标签。

\n
<manifest xmlns:android="http://schemas.android.com/apk/res/android"\n    package="put your own package">\n\n    <application\n        android:allowBackup="true"\n        android:icon="@mipmap/ic_launcher"\n        android:label="@string/app_name"\n        android:roundIcon="@mipmap/ic_launcher_round"\n        android:supportsRtl="true"\n        android:theme="@style/AppTheme">\n        \n        <activity android:name=".broadcast.activity.ScreenOnOffActivity">\n            <intent-filter>\n                <action android:name="android.intent.action.MAIN" />\n\n                <category android:name="android.intent.category.LAUNCHER" />\n            </intent-filter>\n        </activity>\n\n        <service android:enabled="true" android:name=".broadcast.service.ScreenOnOffBackgroundService" />\n    </application>\n\n</manifest>\n
Run Code Online (Sandbox Code Playgroud)\n

3.1.3 将 Activity Java 代码更改为以下。

\n

请注意启动服务对象的java代码。

\n
Intent backgroundService = new Intent(getApplicationContext(), ScreenOnOffBackgroundService.class);\nstartService(backgroundService);\n
Run Code Online (Sandbox Code Playgroud)\n

ScreenOnOffActivity.java

\n
import android.content.Intent;\nimport android.os.Bundle;\nimport android.support.v7.app.AppCompatActivity;\nimport android.util.Log;\n\nimport com.dev2qa.example.R;\nimport com.dev2qa.example.broadcast.receiver.ScreenOnOffReceiver;\nimport com.dev2qa.example.broadcast.service.ScreenOnOffBackgroundService;\n\npublic class ScreenOnOffActivity extends AppCompatActivity {\n\n    private ScreenOnOffReceiver screenOnOffReceiver = null;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_screen_on_off);\n\n        setTitle("dev2qa.com - Keep BroadcastReceiver Running After App Exit.");\n\n        Intent backgroundService = new Intent(getApplicationContext(), ScreenOnOffBackgroundService.class);\n        startService(backgroundService);\n\n        Log.d(ScreenOnOffReceiver.SCREEN_TOGGLE_TAG, "Activity onCreate");\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        Log.d(ScreenOnOffReceiver.SCREEN_TOGGLE_TAG, "Activity onDestroy");\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

再次运行该示例,您可以看到下图。从logcat输出中,我们可以看到广播接收器在android应用程序退出后仍在运行。

\n

Android 保持广播接收器 GIF
\n (来源:dev2qa.com

\n