zoukankan      html  css  js  c++  java
  • 【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),菜单键

  • 相关阅读:
    InvokeRequired和Invoke
    DataGrid 得到DataGridRow 和DataGridColumn
    DataGrid 如何得到DataGridRow 和DataGridCell 对象
    安装Extended WPF Toolkit
    WPF DataGrid绑定一个组合列
    允许Root登录Docker ubuntu(MAC主机,使用portainer管理)
    photoshop人物美白教程:暗沉肤色提亮美白
    django中聚合aggregate和annotate GROUP BY的使用方法
    Django Model 基础数据库操作应用
    如何在mac上安装gitlab
  • 原文地址:https://www.cnblogs.com/HDK2016/p/8463846.html
Copyright © 2011-2022 走看看