Android息屏状态下启动App

需求简介

设备在息屏的状态下,通过特定的物理按键去启动Camera应用。

分析

设备在息屏状态下(系统处于休眠),直接通过startActivity方法去启动应用是无效的。
所以将需求的实现应该分为两步:
1、点亮屏幕(唤醒系统);
2、通过startActivity方法启动App;

1、点亮屏幕

我对这个需求的实现代码是写在frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java 中的。

PowerManager mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
private void lightScreen(String keyName){
    if (!mPowerManager.isScreenOn()) {
    	mPowerManager.wakeUp(SystemClock.uptimeMillis());	
    }
}

2、通过startActivity方法启动App

需要判断一下设备是否处于锁屏状态,因为不同状态下启动App所用到的action是不同的。

//CAMERA_PACKAGE_NAME 为camera应用的包名
private final String CAMERA_PACKAGE_NAME = "com.app.camera";
private void launchApp(){
	Intent intent;
    if (isOnLockScreenPage()) {
    	intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
                	    .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
        startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
        //startActivityAsUser是PhoneWindowManager中的已有方法
    } else {
         intent = mContext.getPackageManager().getLaunchIntentForPackage(CAMERA_PACKAGE_NAME);
         intent.setAction(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
         startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
    }
}
//判断设备是否处于锁屏状态
private boolean isOnLockScreenPage(){
    KeyguardManager mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
    return mKeyguardManager.inKeyguardRestrictedInputMode();
}

启动失败问题

在设备处于锁屏且息屏的状态下,通过物理按键事件启动Camera App存在概率性失败的bug。

原因

因为在唤醒系统后即刻执行Camera相应组件的初始化操作,耗费的时间比正常状态下要久一些,而系统在frameworks/base/services/core/java/com/android/server/am/ActivityStack.java中对App的响应做了一个时间限制(500ms),超过该时间会认为启动的App是未响应状态,从而取消对该App的启动。
我所用设备从息屏状态下启动的Camera的响应时间估计在500ms上下,所以导致概率性失败的问题。

解决

在ActivityStack.java的schedulePauseTimeout中对从息屏状态下启动Camera的情况,适当的延长了响应超时时间。

/**
* Schedule a pause timeout in case the app doesn't respond. We don't give it much time because
* this directly impacts the responsiveness seen by the user.
*/
private void schedulePauseTimeout(ActivityRecord r) {
    final Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
    msg.obj = r;
    r.pauseTime = SystemClock.uptimeMillis();
    //属性persist.sys.camera_prop在息屏状态下启动Camera的时候设置为true
    if (SystemProperties.getBoolean("persist.sys.camera_prop", false)) {
         mHandler.sendMessageDelayed(msg, 1000);
         SystemProperties.set("persist.sys.camera_prop", "0");
     } else {
         //PAUSE_TIMEOUT = 500
         mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
     }
     if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete...");
}
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Android 应用程序中保持应用在息屏状态下继续运行,可以使用以下两种方法: 1. 使用 WakeLock:可以使用 WakeLock 来保持设备处于唤醒状态。WakeLock 可以防止设备在息屏时进入休眠模式。以下是使用 WakeLock 的示例代码: ```java PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyApp:MyWakeLockTag"); wakeLock.acquire(); // 在这里执行需要在息屏状态下继续运行的操作 wakeLock.release(); ``` 请确保在使用完 WakeLock 后调用 `release()` 方法来释放 WakeLock。 2. 使用 Foreground Service:可以将应用程序设置为前台服务,这样即使在息屏状态下,应用程序也可以持续运行。以下是使用前台服务的示例代码: ```java public class MyForegroundService extends Service { private static final int NOTIFICATION_ID = 1; private static final String CHANNEL_ID = "MyForegroundServiceChannel"; @Override public void onCreate() { super.onCreate(); // 创建通知渠道(仅适用于 Android 8.0 及更高版本) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Foreground Service Channel", NotificationManager.IMPORTANCE_DEFAULT); NotificationManager notificationManager = getSystemService(NotificationManager.class); notificationManager.createNotificationChannel(channel); } // 创建通知 Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("My App") .setContentText("App is running in background") .setSmallIcon(R.drawable.ic_notification) .build(); // 开始前台服务 startForeground(NOTIFICATION_ID, notification); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // 在这里执行需要在息屏状态下继续运行的操作 return START_STICKY; } @Override public void onDestroy() { super.onDestroy(); // 停止前台服务 stopForeground(true); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } } ``` 要使用前台服务,需要在 AndroidManifest.xml 文件中声明服务,并请求必要的权限。确保在启动服务时调用 `startService()` 方法。 这些方法可以让您的应用程序在 Android 设备的息屏状态下继续运行。但是,请注意这可能会对设备的电池寿命产生一定影响,因为应用程序会持续占用设备资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值