目錄結構:
最近筆者在做一個功能,就是實現Android程序在鎖屏后可以繼續運行,筆者在網上查了一些資料,現在整理出來,希望能夠對你有所幫助。
1.如何監聽屏幕鎖屏
監聽屏幕鎖屏可以通過如下方式來實現,直接通過代碼來判定,或通過監聽器來實現
如何實現Android程序在手機鎖屏后繼續運行
1)通過代碼來判定屏幕的鎖屏狀態
可以通過PowerManager的isScreenOn方法,代碼如下:
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); //如果為true,則表示屏幕“亮”了,否則屏幕“暗”了。 boolean isScreenOn = pm.isScreenOn();
這里需要解釋一下:
屏幕“亮”,表示有兩種狀態:a、未鎖屏 b、目前正處於解鎖狀態 。這兩種狀態屏幕都是亮的;
屏幕“暗”,表示目前屏幕是黑的 。
通過KeyguardManager的inKeyguardRestrictedInputMode方法,也可以實現判斷屏幕的鎖屏狀態
KeyguardManager mKeyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); boolean flag = mKeyguardManager.inKeyguardRestrictedInputMode();
對flag進行一下說明,經過試驗,總結為:
如果flag為true,表示有兩種狀態:a、屏幕是黑的 b、目前正處於鎖屏狀態 。
如果flag為false,表示目前未鎖屏
當然也可以通過反射的方式來調用上面的兩種方法:
Method mReflectScreenState; try { mReflectScreenState = PowerManager.class.getMethod(isScreenOn, new Class[] {}); PowerManager pm = (PowerManager)
context.getSystemService(Activity.POWER_SERVICE); boolean isScreenOn= (Boolean) mReflectScreenState.invoke(pm); } catch (Exception e) { e.printStackTrace()
2)通過監聽器來判定屏幕的鎖屏狀態
當安卓系統鎖屏或者屏幕亮起,或是屏幕解鎖的時候,系統內部都會發送相應的廣播,我們只需要對廣播進行監聽就可以了
注冊廣播的偽代碼如下:
ScreenBroadcastReceiver mScreenReceiver; class ScreenBroadcastReceiver extends BroadcastReceiver { String action = null; @Override public void onReceive(Context context, Intent intent) { action = intent.getAction(); if (Intent.ACTION_SCREEN_ON.equals(action)) { // 開屏 } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // 鎖屏 } else if (Intent.ACTION_USER_PRESENT.equals(action)) { // 解鎖 } } } private void startScreenBroadcastReceiver() { IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_USER_PRESENT); context.registerReceiver(mScreenReceiver, filter); }
2.如何實現手機屏幕在鎖屏后繼續運行
在上面我們知道了如何監聽屏幕的狀態,接下要實現如何在屏幕關閉后程序不停止運行。關於這個功能,筆者在網上搜索了一些資料,Android的WakeLock機制就是其中一種,使用Android的service也可以。但是經過筆者的測試發現效果都不太理想,對於Android版本的兼容性不強,筆者的Android4.4可以支持,但是Android6.0經過測試發現卻不支持。
下面筆者介紹一種萬能方法,在這里感謝知乎給我提出的意見(聽說是QQ鎖屏的黑科技呢)。
就是在屏幕鎖屏的時候,跳轉到另一個界面,該界面只有一個像素點。
代碼如下:
MainActivity.java

package org.screenlock.main; import java.lang.reflect.Method; import java.util.Date; import java.util.Timer; import java.util.TimerTask; import com.example.screenlocktest.R; import android.os.Build; import android.os.Bundle; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.app.Activity; import android.app.KeyguardManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.PixelFormat; import android.text.format.Time; import android.util.DisplayMetrics; import android.util.Log; import android.view.Gravity; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { Context context = null; Intent mintent=null; static Activity mactivity=null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.context = this; mintent=new Intent(this,SinglePixelActivity.class); startScreenBroadcastReceiver(new ScreenBroadcastReceiver()); Timer timer=new Timer(); TimerTask timerTask=new TimerTask() { @Override public void run() { Log.i("info", new Date().toString()); } }; timer.schedule(timerTask, 0,10* 1000);//每10秒鍾運行一次,用於觀察程序是否在運行 } /** * 注冊屏幕廣播 */ private void startScreenBroadcastReceiver(ScreenBroadcastReceiver mScreenReceiver) { IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_USER_PRESENT); context.registerReceiver(mScreenReceiver, filter); } private class ScreenBroadcastReceiver extends BroadcastReceiver { private String action = null; @Override public void onReceive(Context context, Intent intent) { action = intent.getAction(); if (Intent.ACTION_SCREEN_ON.equals(action)) { // 開屏 Log.i("info", "開屏"); finishScreenActivity(); } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // 鎖屏 Log.i("info", "鎖屏"); startScreenActivity(); } else if (Intent.ACTION_USER_PRESENT.equals(action)) { // 解鎖 Log.i("info", "解屏"); } } } /** * 關閉屏幕鎖屏界面 */ private void finishScreenActivity(){ if(mactivity!=null){ mactivity.finish(); } } /** * 跳轉到屏幕鎖屏界面 */ private void startScreenActivity(){ startActivity(mintent); } }
SinglePixelActivity.java

package org.screenlock.main; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.Window; import android.view.WindowManager; public class SinglePixelActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Window window= getWindow(); WindowManager.LayoutParams params=new WindowManager.LayoutParams(); params.x=0; params.y=0; params.width=1; params.height=1; window.setAttributes(params); MainActivity.mactivity=this; Log.i("info", "SinglePixelActivity onCreate"); } @Override protected void onStart() { super.onStart(); Log.i("info", "SinglePixelActivity onStart"); } @Override protected void onResume() { super.onResume(); Log.i("info", "SinglePixelActivity onResume"); } @Override protected void onPause() { super.onPause(); Log.i("info", "SinglePixelActivity onPause"); } @Override protected void onStop() { super.onStop(); Log.i("info", "SinglePixelActivity onStop"); } @Override protected void onRestart() { super.onRestart(); Log.i("info", "SinglePixelActivity onRestart"); } @Override protected void onDestroy() { super.onDestroy(); Log.i("info", "SinglePixelActivity onDestroy"); } }
AndroidManifest.xml中需要添加如下:
<activity android:name="org.screenlock.main.SinglePixelActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
運行上面的程序,可以看到計時器在正常打印東西,說明程序並沒有完全停止,還可以看到打印如下的日志:
info SinglePixelActivity onCreate
info SinglePixelActivity onStart
info SinglePixelActivity onResume
info SinglePixelActivity onPause
info SinglePixelActivity onStop
從日志中可以看出,當鎖屏后,這個SinglePixelActivity立即進入了OnStop狀態,在Onstop的狀態的頁面是很有可能被系統回收的。因此可以再配合上WakeLock機制,若WakeLock不合適的話,那么可以嘗試播放無聲音樂。保持系統不回收該App的資源。
需要注意,當鎖屏后再次打開的跳轉邏輯處理也是一個問題,可以參考 Android實現監聽返回鍵,主鍵(HOME),菜單鍵