【Android】Android屏幕狀態操作


目錄結構:

contents structure [+]

 

最近筆者在做一個功能,就是實現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);
    }
}
MainActivity.java

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");
    }
    
}
SinglePixelActivity.java

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),菜單鍵

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM