通过推送消息控制Android系统锁屏、唤醒

最近一年以来,博主一直在搞密室逃脱方面的东西。涉及到的技术很杂,不少也很冷门。

前段时间有这样一个有意思的需求:要求服务器在达到一定条件时唤醒一台待机的投影仪自动进行播放,并且在不同的条件下播放不同的影片。

博主考察了一下市场发现现在市面上有这样几种投影仪:

  1. 普通投影仪,需要接一台电脑,在电脑上选择播放的影片,电脑显示什么投影仪做为显示设备就播放什么。这个想做自动化需要和播放影片的电脑进行通讯,但一台电脑只作为一个视频播放器使用有点大材小用。
  2. 可以插U盘的投影仪,这种投影仪很好的取代了播放设备,直接读取U盘中的内容,在投影仪上播放。这类投影仪一般只能用遥控器进行控制,不能被服务器控制,所以也不可取。
  3. 最后博主在某宝上发现了一种小型带Android系统的投影仪,就是这个样子了,名字叫CooLux(中文名酷乐视),有兴趣的朋友可以搜索一下。

    这个小型投影仪本身带Android系统,传统实体按键变成了面板上的上、下、左、右、OK、返回、菜单按键,屏幕变成了投影灯泡,把影像直接投到墙上。有了Android系统就意味着可以像控制手机一样去控制这台投影仪,什么选择影片、无线通讯、控制待机、唤醒什么的都不是问题。

虽然它本身自带Android系统,但这是一款经过深度定制的Android系统,和我们平时在手机上用的还有很多不一样。例如它的画面显示是固定横屏的,没有锁屏界面,投影开启永远不会待机等等。其他的问题还好,不待机的问题很严重,因为该投影仪的使用环境基本上是一整天都要开启,只有收到播放影片的命令才会进行播放,投影仪消耗电能最大的就是投影灯泡部分了。大量的电能会转换成热量,所以一般的投影仪都会配备一款功率比较高的风扇。这就需要我们去在程序中控制投影仪在播放完影片后主动关闭屏幕,在播放影片之前主动唤醒屏幕。


现在需求来了,投影仪如何接到推送消息然后自动唤醒屏幕并在播放完毕后自动关闭屏幕?我的解决思路如下:

  1. 在服务器上安装androidpn服务程序,对在线手机进行推送(请大家自行参考androidpn教程)。
  2. 应用中集成androidpn-client接收推送消息(请大家自行参考androidpn教程)。
  3. 改造androidpn-client,在收到推送消息后,向主Activity发送intent,传送推送消息内容(其中包括要播放哪部影片的索引)。
    在androidpn-client的NotificationReceiver类onReceive函数中,我们在收到消息后不吧消息交给Notifier处理,而是直接向主Activity发送intent。
    //            Notifier notifier = new Notifier(context);
    //            notifier.notify(notificationId, notificationApiKey,
    //                    notificationTitle, notificationMessage, notificationUri,notificationFrom,packetId);
    
                //直接转到对应的Activity
                Intent nintent = new Intent(context,ProjectorPlayerActivity.class);
                nintent.putExtra(Constants.NOTIFICATION_ID,notificationId);
                nintent.putExtra(Constants.NOTIFICATION_API_KEY,notificationApiKey);
                nintent.putExtra(Constants.NOTIFICATION_TITLE,notificationTitle);
                nintent.putExtra(Constants.NOTIFICATION_MESSAGE,notificationMessage);
                nintent.putExtra(Constants.NOTIFICATION_URI,notificationUri);
                nintent.putExtra(Constants.NOTIFICATION_FROM, notificationFrom);
                nintent.putExtra(Constants.PACKET_ID, packetId);
                nintent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    
                context.startActivity(nintent);
    


  4. Activity收到intent后,判断屏幕是否关闭,如果关闭执行唤醒屏幕操作,再对消息中指定的影片进行播放。
    Activity的onNewIntent函数处理获得的intent
        @Override
        protected void onNewIntent(Intent intent) {
            super.onNewIntent(intent);
            String urivalue = intent.getStringExtra(Constants.NOTIFICATION_URI);
            if(urivalue==null || urivalue.equals(""))		//判断URI消息是否有效
                return;
            DeviceUtils.vibrate(this, 500);				//让手机振动500ms
            if(DeviceUtils.isScreenLocked(this))			//判断手机是否处于屏幕关闭状态
                DeviceUtils.wakeScreen(this);			//如果处于关闭屏幕状态则唤醒屏幕
    
    	<span style="white-space:pre">			</span>//此处做播放影片的处理
        }
    DeviceUtils类的内容如下,主要对硬件设备进行一些操作,目前包括振动、唤醒屏幕、关闭屏幕
    /**
     * 设备工具类,操作一些硬件设备功能
     * Created by fengchong on 16/1/18.
     */
    public class DeviceUtils {
    
        //锁屏部分-------------------------
        //继承了设备管理器的广播类,没做任何操作
        public static class AdminReceiver extends DeviceAdminReceiver{}
        private  static DevicePolicyManager policyManager;
        private static ComponentName componentName;
        private static final int MY_REQUEST_CODE = 9999;
    
        /**
         * 初始化锁屏
         * @param context
         */
        public static void initLockScreen(Context context){
            policyManager = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
            componentName = new ComponentName(context,DeviceUtils.AdminReceiver.class);
        }
    
        /**
         * 激活设备管理器,设置app为激活状态
         */
        public static void activeDeviceManager(Activity activity){
            Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
            intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,componentName);
            intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,"激活一键锁屏");
            activity.startActivityForResult(intent, MY_REQUEST_CODE);
        }
    
        /**
         * 判断是否处于锁屏状态
         * @param c
         * @return	返回ture为锁屏,返回flase为未锁屏
         */
        public final static boolean isScreenLocked(Context c) {
            KeyguardManager km = (KeyguardManager) c.getSystemService(c.KEYGUARD_SERVICE);
            return km.inKeyguardRestrictedInputMode();
        }
    
        /**
         * 被Activity的onActivityResult函数调用
         * @param activity
         * @param requestCode
         * @param resultCode
         * @param data
         */
        public static void onActivityResult(Activity activity,int requestCode,int resultCode,Intent data){
            if(requestCode==MY_REQUEST_CODE && resultCode== Activity.RESULT_OK){
                policyManager.lockNow();
                activity.finish();
            }else{
                activity.finish();
            }
        }
    
        /**
         * 锁定屏幕操作
         * @param activity
         */
        public static void lockScreen(Activity activity){
            if(policyManager.isAdminActive(componentName)){
                policyManager.lockNow();
                activity.finish();
            }else{
                activeDeviceManager(activity);
            }
        }
        //锁屏部分-------------------------
    
        //唤醒屏幕部分----------------------
        private static KeyguardManager km;                                                                                         //键盘管理
        private static PowerManager pm;                                                                                            //电源管理
        private static PowerManager.WakeLock wakeLock;                                                                             //屏幕唤醒对象
    
        /**
         * 初始化唤醒屏幕
         * @param activity
         */
        public static void initWakeScrenUnlock(Activity activity){
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
            pm = (PowerManager) activity.getSystemService(Context.POWER_SERVICE);
            wakeLock = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_DIM_WAKE_LOCK,"bright");
            wakeLock.acquire();
        }
    
        /**
         * 唤醒屏幕
         */
        public static void wakeScreen(Activity activity){
            //屏幕解锁
            km= (KeyguardManager) activity.getSystemService(Context.KEYGUARD_SERVICE);
            KeyguardManager.KeyguardLock kl = km.newKeyguardLock("unLock");
            kl.disableKeyguard();
    
            //屏幕唤醒
            if(wakeLock==null) {
                pm = (PowerManager) activity.getSystemService(Context.POWER_SERVICE);
                wakeLock = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_DIM_WAKE_LOCK,"bright");
            }
            wakeLock.acquire();
            wakeLock.release();
        }
        //唤醒屏幕部分----------------------
    
        //手机振动部分部分----------------------
        /**
         * 手机震动函数
         * @param activity
         * @param milliseconds
         */
        public static void vibrate(final Activity activity, long milliseconds) {
            Vibrator vib = (Vibrator) activity.getSystemService(Service.VIBRATOR_SERVICE);
            vib.vibrate(milliseconds);
        }
    
        //手机振动部分部分----------------------
    }
    

    关闭屏幕部分参考了这篇文章(表示感谢)http://www.cnblogs.com/tianzhijiexian/p/3920257.html,其中还会包含其他一些资源文件大家可自行参考。

    唤醒屏幕部分除了以上的代码还需要在AndroidManifest.xml中加入权限
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />


  5. 影片播放后自动执行关闭屏幕操作,节约电能。
    在合适的位置直接执行DeviceUtils.lockScreen函数既可。
    源码在这里:https://github.com/sorcerer310/BakerStreet42ProjectorPlayer



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值