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

标签 java android service

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

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

这个答案来自 Lars D尽管它被接受了,但应该对 Activity 有效的方法也不起作用。

@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);
}

有一个app我打算这样做,我安装了它,但它仍然不起作用,也许他们使用的 API 已贬值,甚至已被删除。

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

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

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

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

最佳答案

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

现在解决的问题:

  1. 即使我的应用程序被终止/销毁或从系统托盘中删除,它也始终在后台运行。
  2. 该服务始终会在单击 POWER_BUTTON 时监听。
  3. SDK 支持此功能,因为它仅使用广播接收器和服务。

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

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

ScreenOnOffReceiver.java

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class ScreenOnOffReceiver extends BroadcastReceiver {

private final static String SCREEN_TOGGLE_TAG = "SCREEN_TOGGLE_TAG";

@Override
public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();
    if(Intent.ACTION_SCREEN_OFF.equals(action))
    {
        Log.d(SCREEN_TOGGLE_TAG, "Screen is turn off.");
    }else if(Intent.ACTION_SCREEN_ON.equals(action))
    {
        Log.d(SCREEN_TOGGLE_TAG, "Screen is turn on.");
    }}
}

<强>2。在 Activity 中注册和取消注册 ScreenOnOffReceiver。

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

ScreenOnOffActivity.java

import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import com.dev2qa.example.R;
import com.dev2qa.example.broadcast.receiver.ScreenOnOffReceiver;

public class ScreenOnOffActivity extends AppCompatActivity {

    private ScreenOnOffReceiver screenOnOffReceiver = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_screen_on_off);

        setTitle("dev2qa.com - Keep BroadcastReceiver Running After App Exit.");

        // Create an IntentFilter instance.
        IntentFilter intentFilter = new IntentFilter();

        // Add network connectivity change action.
        intentFilter.addAction("android.intent.action.SCREEN_ON");
        intentFilter.addAction("android.intent.action.SCREEN_OFF");

        // Set broadcast receiver priority.
        intentFilter.setPriority(100);

        // Create a network change broadcast receiver.
        screenOnOffReceiver = new ScreenOnOffReceiver();

        // Register the broadcast receiver with the intent filter object.
        registerReceiver(screenOnOffReceiver, intentFilter);

        Log.d(ScreenOnOffReceiver.SCREEN_TOGGLE_TAG, "onCreate: screenOnOffReceiver is registered.");

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        // Unregister screenOnOffReceiver when destroy.
        if(screenOnOffReceiver!=null)
        {
            unregisterReceiver(screenOnOffReceiver);
            Log.d(ScreenOnOffReceiver.SCREEN_TOGGLE_TAG, "onDestroy: screenOnOffReceiver is unregistered.");
        }
    }
}

按照以下步骤运行上述 Activity 。

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

Runnindg Activity

<强>3。在Android后台服务中注册和取消注册广播接收器

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

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

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

3.1 创建Android服务类。

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

ScreenOnOffBackgroundService.java

import android.app.Service;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

import ScreenOnOffReceiver;

public class ScreenOnOffBackgroundService extends Service {

    private ScreenOnOffReceiver screenOnOffReceiver = null;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onCreate() {
        super.onCreate();

        // Create an IntentFilter instance.
        IntentFilter intentFilter = new IntentFilter();

        // Add network connectivity change action.
        intentFilter.addAction("android.intent.action.SCREEN_ON");
        intentFilter.addAction("android.intent.action.SCREEN_OFF");

        // Set broadcast receiver priority.
        intentFilter.setPriority(100);

        // Create a network change broadcast receiver.
        screenOnOffReceiver = new ScreenOnOffReceiver();

        // Register the broadcast receiver with the intent filter object.
        registerReceiver(screenOnOffReceiver, intentFilter);

        Log.d(ScreenOnOffReceiver.SCREEN_TOGGLE_TAG, "Service onCreate: screenOnOffReceiver is registered.");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        // Unregister screenOnOffReceiver when destroy.
        if(screenOnOffReceiver!=null)
        {
            unregisterReceiver(screenOnOffReceiver);
            Log.d(ScreenOnOffReceiver.SCREEN_TOGGLE_TAG, "Service onDestroy: screenOnOffReceiver is unregistered.");
        }
    }
}

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

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="put your own package">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        
        <activity android:name=".broadcast.activity.ScreenOnOffActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:enabled="true" android:name=".broadcast.service.ScreenOnOffBackgroundService" />
    </application>

</manifest>

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

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

Intent backgroundService = new Intent(getApplicationContext(), ScreenOnOffBackgroundService.class);
startService(backgroundService);

ScreenOnOffActivity.java

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import com.dev2qa.example.R;
import com.dev2qa.example.broadcast.receiver.ScreenOnOffReceiver;
import com.dev2qa.example.broadcast.service.ScreenOnOffBackgroundService;

public class ScreenOnOffActivity extends AppCompatActivity {

    private ScreenOnOffReceiver screenOnOffReceiver = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_screen_on_off);

        setTitle("dev2qa.com - Keep BroadcastReceiver Running After App Exit.");

        Intent backgroundService = new Intent(getApplicationContext(), ScreenOnOffBackgroundService.class);
        startService(backgroundService);

        Log.d(ScreenOnOffReceiver.SCREEN_TOGGLE_TAG, "Activity onCreate");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(ScreenOnOffReceiver.SCREEN_TOGGLE_TAG, "Activity onDestroy");
    }
}

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

Android Keep Broadcast Receiver GIF
(来源:dev2qa.com)

关于java - 如何在 Android 中使用后台服务覆盖两次甚至 3 次单击电源按钮甚至音量增大/减小键?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57051157/

相关文章:

Java JDialogs之间如何传递信息?

java - 为什么在代码中放置随机 http 链接不会导致编译错误?

java - 以编程方式外部化 logback-spring.xml

Android - 如何使用 Parse SDK 上传音频文件

c# - 服务无法在 WCF 中找到其他服务的端点

java - Android通知信息不停留在java类ArrayList中

node.js - Firebase Admin Nodejs 找不到模块 service_account.json

java - PKCS12 证书错误

android - 单击 Viewpager Xamarin Android

java.lang.ClassCastException : androidx. appcompat.widget.AppCompatImageButton 无法转换为 android.widget.Button