当前位置: 首页 > 知识库问答 >
问题:

在Android系统中,如何在后台使用一项服务覆盖双击甚至3次电源按钮,甚至是音量上下键?

燕琨
2023-03-14

我正在开发一个应用程序,我可以在3-5秒内连续听到电源按钮被点击3次。

我搜索了所有的答案,但没有一个对我有用。

拉斯·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);
}

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

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

  1. 当应用程序被杀死/销毁且不再检测时

也许我们可以在活动中找到一种方法,但是我想在应用程序被杀死/在后台/当屏幕锁定/当屏幕关闭时,使用服务/广播接收器来收听操作。

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

共有1个答案

寇鸿
2023-03-14

由于没有人试图解决这个问题,或者可能甚至无法理解这个问题,幸运的是,在搜索了很多小时的网页后,我发现了这个非常棒的网站,它完全解决了我的问题,并想把它发布在这里。

现在解决的问题是:

  1. 我的应用程序始终在后台运行,即使它已被杀死/销毁或从系统托盘中删除

我只是写下这些步骤,以防将来链接可能无法工作或被删除:

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.在活动中注册和注销ScreenOnOffReceiver。

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

屏幕无表情。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.");
        }
    }
}

在下面的步骤中运行上面的活动。

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

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

当您在活动中注册广播接收器时,它将在活动退出后停止。

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

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

3.1创建Android服务类。

3.1.1创建扩展android.app.服务的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标记。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将活动Java代码更改为以下内容。

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

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

屏幕无表情。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应用程序退出后仍在运行。

 类似资料:
  • 我现在能够在运行在Websphere服务器上的Java EE项目中自动进行增量编译。 我整理jRebel是因为我在突然启动服务器时遇到了问题,并且注意到现在Intellij正在自动编译,我也能够“几乎”有效地看到更改(比Eclipse慢) 那么,intellij中甚至需要jRebel吗?我对Websphere的设置可以在下图中看到。注意,我只添加了一个Ear文件,它不是分解版本,仍然这是工作。jr

  • 我想在我的应用程序中捕获,也要在后台运行的服务中捕获该事件。为此,我对广播接收器使用了以下代码。 onReceive()方法: 有了这个代码,我能够检测按钮的按下事件内接收器。 现在我想检测电源按钮是否被按下3秒或更长时间,然后我想在接收器内执行特定操作。为此,我找到了这个方法 但我发现这个方法只能在活动中运行,但我想在服务中调用它。 有没有办法检测电源按钮是否按下了3秒钟,或者我们可以在服务内部

  • 我知道,用jsp编写scriptlet代码是一种坏习惯,但我这样做只是为了理解jsp/Servlet的概念。 所以告诉我,为什么这个页面在达到假条件之前关闭标签后还在运行?如何在关闭页签停止它?

  • 在Netbeans中,经过一些研究,我成功地编辑了文件构建。xml来定制IDE生成jar和清单文件的方式。我不得不为Eclipse迁移一个项目,甚至找到了构建jar的选项,但我需要用一些个性化信息构建jar。 我添加了文件构建。xml在我的eclipse项目中作为构建文件ANT,但当我发送并执行它时,eclipse运行两次,一次生成2个jars文件。 遵循我的文件构建。xml: 需要指出的是,ec

  • 创建restful应用程序,但它不会以XML格式返回响应。即使在点击URL时控制台上也没有日志“http://localhost:8080/message/webapi/messages". 我返回一个列表,并使用@products(MediaType.APPLICATION\uxml)以XML形式返回响应。 消息资源。Java语言 Message.java 如果我不使用@XMLRootEleme

  • 我下载了适用于Windows的Ruby安装程序,安装了Ruby,然后进行了尝试 错误:执行gem时。。。(Gem::RemoteFetcher::FetchError) SSL_connect返回=1 errno=0 state=SSLv3读取服务器证书B:证书验证失败(https://api.rubygems.org/specs.4.8.gz) 更新已安装的宝石 错误:执行gem时。。。(Gem