前阵子收到客户要求,要做一款安卓手机和平板上使用的屏保,其实蛮奇怪的,电脑用屏保倒是见得多了,可是手机不使用的时候关掉屏幕不就OK了吗?话说现在的智能手机电池都不耐用的可怜,还装屏保岂不是很费电。原来客户是用于放在营业厅(手机相关),通过手机或者平板来使用相关设备投射到电子屏幕上展示广告的用途,24小时不断电,只是展示用,故电量不作考虑。要求在服务端上传欲展示的图片,PDA上可以进行获取更新图片,只要不断滚动他们的广告就可以了。起初并不是我来做的,同事已经都写的差不多了,他突然有别的项目很急,留给我来做,也好,以前没做过,顺便了解一下android屏保相关的知识,写下来做积累。
-------------------------------------------------------------------------------------------------------
首先接触到了KeyguardManager,用来对系统的屏保进行屏蔽
public class KeyguardManager extends Object
Class that can be used to lock and unlock the keyboard. Get an instance of this class by calling Context.getSystemService(java.lang.String) with argument Context.KEYGUARD_SERVICE. The actual class to control the keyboard locking is KeyguardManager.KeyguardLock.
一个用于锁屏和解锁的类,通过调用Context.getSystemService(Context.KEYGUARD_SERVICE)来获取实例。实际上用于操控锁屏的是KeyguardManager.KeyguardLock类
KeyguardManager 两个内部类分别是:
(1)KeyguardManager.KeyguardLock(l两个函数)
记得加权限
<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
disableKeyguard()函数来解除锁屏
reenableKeyguard()反解除锁屏.reenableKeyguard()反解除锁屏的意思是:如果在调用disableKeyguard()函数之前是锁屏的,那么就进行锁屏,否则不进行任何操作。当然如果之前没调用disableKeyguard()函数,也不进行任何操作。
(2)KeyguardManager.OnKeyguardExitResult(boolean success) :返回true表示exitKeyguardSecurely()函数执行成功,否则表示失败<具体自己没用到,是个做判断和debug用的吧估计>
-----------------------------------------------------------------------------------------------------
而后用到的是开启和关闭屏幕唤醒的内容,PowerManager和WakeLock这部分之前用到过,不在详述,这次把这部分单独写成一个工具类,简化代码
- package com.eyu.screen.util;
- import android.content.Context;
- import android.os.PowerManager;
- import android.os.PowerManager.WakeLock;
- public class PowerManagerWakeLock {
- private static WakeLock wakeLock;
- /**开启 保持屏幕唤醒*/
- public static void acquire(Context context) {
- PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- wakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE, "PowerManagerWakeLock");
- wakeLock.acquire();
- }
- /**关闭 保持屏幕唤醒*/
- public static void release() {
- if (wakeLock != null) {
- wakeLock.release();
- wakeLock = null;
- }
- }
- }
package com.eyu.screen.util; import android.content.Context; import android.os.PowerManager; import android.os.PowerManager.WakeLock; public class PowerManagerWakeLock { private static WakeLock wakeLock; /**开启 保持屏幕唤醒*/ public static void acquire(Context context) { PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); wakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE, "PowerManagerWakeLock"); wakeLock.acquire(); } /**关闭 保持屏幕唤醒*/ public static void release() { if (wakeLock != null) { wakeLock.release(); wakeLock = null; } } }
-------------------------------------------------------------------------------------------------------------------------------------------
其实最主要的应该就是上面的内容,后续就是编写Service和发送广播的操作,并实现和服务端的通信。
做完之后抛开服务端和下载更新的内容,自己做了一个单机用的留底,基本思路和操作与公司项目的一致,只是图片需要手动添加而已,使用后会一直监听屏幕的状态,一旦屏幕灭掉会立刻唤醒,使用viewpager和定时器来控制图片自动的翻页,想彻底停掉就需要断掉后台的service,下面是小程序的截图,启动后会先做判断,如果sd卡指定目录没有图片的话,则加载资源文件,有图片加载SD卡中的。
Service的代码:
- package com.eyu.screen.UI;
- import com.eyu.screen.util.PowerManagerWakeLock;
- import android.app.KeyguardManager;
- import android.app.Service;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.os.IBinder;
- public class ScreenSaverS extends Service {
- @Override
- public IBinder onBind(Intent intent) {
- // TODO Auto-generated method stub
- return null;
- }
- public void onCreate() {
- // 屏蔽系统的屏保
- KeyguardManager manager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
- KeyguardManager.KeyguardLock lock = manager
- .newKeyguardLock("KeyguardLock");
- lock.disableKeyguard();
- // 注册一个监听屏幕开启和关闭的广播
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_SCREEN_ON);
- filter.addAction(Intent.ACTION_SCREEN_OFF);
- registerReceiver(screenReceiver, filter);
- }
- BroadcastReceiver screenReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- // TODO Auto-generated method stub
- String action = intent.getAction();
- if (action.equals(Intent.ACTION_SCREEN_ON)) {
- } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {//如果接受到关闭屏幕的广播
- if (!ScreenSaverShowA.isShow) {
- //开启屏幕唤醒,常亮
- PowerManagerWakeLock.acquire(ScreenSaverS.this);
- }
- PowerManagerWakeLock.acquire(ScreenSaverS.this);
- Intent intent2 = new Intent(ScreenSaverS.this,
- ScreenSaverShowA.class);
- intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent2);
- PowerManagerWakeLock.release();
- }
- }
- };
- public void onDestroy() {
- PowerManagerWakeLock.release();
- unregisterReceiver(screenReceiver);
- };
- }
package com.eyu.screen.UI; import com.eyu.screen.util.PowerManagerWakeLock; import android.app.KeyguardManager; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.IBinder; public class ScreenSaverS extends Service { @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } public void onCreate() { // 屏蔽系统的屏保 KeyguardManager manager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); KeyguardManager.KeyguardLock lock = manager .newKeyguardLock("KeyguardLock"); lock.disableKeyguard(); // 注册一个监听屏幕开启和关闭的广播 IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); registerReceiver(screenReceiver, filter); } BroadcastReceiver screenReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub String action = intent.getAction(); if (action.equals(Intent.ACTION_SCREEN_ON)) { } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {//如果接受到关闭屏幕的广播 if (!ScreenSaverShowA.isShow) { //开启屏幕唤醒,常亮 PowerManagerWakeLock.acquire(ScreenSaverS.this); } PowerManagerWakeLock.acquire(ScreenSaverS.this); Intent intent2 = new Intent(ScreenSaverS.this, ScreenSaverShowA.class); intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent2); PowerManagerWakeLock.release(); } } }; public void onDestroy() { PowerManagerWakeLock.release(); unregisterReceiver(screenReceiver); }; }
屏保展示页面代码:
- <SPAN style="FONT-SIZE: 12px">package com.eyu.screen.UI;
- import java.io.File;
- import java.util.Timer;
- import java.util.TimerTask;
- import com.eyu.screen.R;
- import com.eyu.screen.adapter.ScreenSaverShowAdapter;
- import com.eyu.screen.util.FolderUtil;
- import android.annotation.SuppressLint;
- import android.app.Activity;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.drawable.Drawable;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.support.v4.view.ViewPager;
- import android.util.Log;
- import android.view.View;
- import android.view.View.OnClickListener;
- @SuppressLint("HandlerLeak")
- public class ScreenSaverShowA extends Activity {
- public static boolean isShow = false;
- private ViewPager viewPager;
- private Bitmap[] bmps = null;
- private Drawable[] drawables = new Drawable[5];
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
- setContentView(R.layout.screenshow);
- isShow = true;
- initControl();
- autoSwitch();
- }
- @Override
- protected void onDestroy() {
- // TODO Auto-generated method stub
- isShow = false;
- //将bitmap回收,尽量避免OOM
- if (bmps != null) {
- for (int i = 0; i < bmps.length; i++) {
- bmps[i].recycle();
- }
- } else {
- return;
- }
- super.onDestroy();
- }
- private void initControl() {
- findViewById(R.id.btn_jiesuo).setOnClickListener(new OnClick());
- viewPager = (ViewPager) findViewById(R.id.viewpager);
- File f = new File(FolderUtil.getSaveFolder());
- File[] files = f.listFiles();// 得到所有子目录
- bmps = new Bitmap[files.length];
- //如果文件夹为空,则从资源文件加载图片
- if (files.length == 0) {
- drawables[0] = getResources().getDrawable(R.drawable.bg_01);
- drawables[1] = getResources().getDrawable(R.drawable.bg_02);
- drawables[2] = getResources().getDrawable(R.drawable.bg_03);
- drawables[3] = getResources().getDrawable(R.drawable.bg_04);
- drawables[4] = getResources().getDrawable(R.drawable.bg_05);
- ScreenSaverShowAdapter adapter = new ScreenSaverShowAdapter(
- ScreenSaverShowA.this, drawables);
- viewPager.setAdapter(adapter);
- } else {
- //文件夹不为空则循环遍历加载sd卡指定目录中图片
- for (int i = 0; i < files.length; i++) {
- String path = files[i].getAbsolutePath();
- bmps[i] = BitmapFactory.decodeFile(path);
- Log.d("PDA", "====H===" + path);
- }
- ScreenSaverShowAdapter adapter = new ScreenSaverShowAdapter(
- ScreenSaverShowA.this, bmps);
- viewPager.setAdapter(adapter);
- }
- }
- /** 图片定时自动切换 */
- private void autoSwitch() {
- int interval = 3000;
- Timer timer = new Timer();
- TimerTask task = new TimerTask() {
- @Override
- public void run() {
- // TODO Auto-generated method stub
- Message message = new Message();
- handler.sendMessage(message);
- }
- };
- timer.schedule(task, interval, interval);
- }
- Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- int currentPage = viewPager.getCurrentItem();
- int tempNum = bmps.length == 0 ? drawables.length : bmps.length;
- int nextPage = (currentPage + 1) % tempNum;
- viewPager.setCurrentItem(nextPage);
- super.handleMessage(msg);
- }
- };
- class OnClick implements OnClickListener {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- ScreenSaverShowA.this.finish();
- }
- }
- }
- </SPAN>
package com.eyu.screen.UI;
import java.io.File;
import java.util.Timer;
import java.util.TimerTask;
import com.eyu.screen.R;
import com.eyu.screen.adapter.ScreenSaverShowAdapter;
import com.eyu.screen.util.FolderUtil;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
@SuppressLint("HandlerLeak")
public class ScreenSaverShowA extends Activity {
public static boolean isShow = false;
private ViewPager viewPager;
private Bitmap[] bmps = null;
private Drawable[] drawables = new Drawable[5];
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.screenshow);
isShow = true;
initControl();
autoSwitch();
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
isShow = false;
//将bitmap回收,尽量避免OOM
if (bmps != null) {
for (int i = 0; i < bmps.length; i++) {
bmps[i].recycle();
}
} else {
return;
}
super.onDestroy();
}
private void initControl() {
findViewById(R.id.btn_jiesuo).setOnClickListener(new OnClick());
viewPager = (ViewPager) findViewById(R.id.viewpager);
File f = new File(FolderUtil.getSaveFolder());
File[] files = f.listFiles();// 得到所有子目录
bmps = new Bitmap[files.length];
//如果文件夹为空,则从资源文件加载图片
if (files.length == 0) {
drawables[0] = getResources().getDrawable(R.drawable.bg_01);
drawables[1] = getResources().getDrawable(R.drawable.bg_02);
drawables[2] = getResources().getDrawable(R.drawable.bg_03);
drawables[3] = getResources().getDrawable(R.drawable.bg_04);
drawables[4] = getResources().getDrawable(R.drawable.bg_05);
ScreenSaverShowAdapter adapter = new ScreenSaverShowAdapter(
ScreenSaverShowA.this, drawables);
viewPager.setAdapter(adapter);
} else {
//文件夹不为空则循环遍历加载sd卡指定目录中图片
for (int i = 0; i < files.length; i++) {
String path = files[i].getAbsolutePath();
bmps[i] = BitmapFactory.decodeFile(path);
Log.d("PDA", "====H===" + path);
}
ScreenSaverShowAdapter adapter = new ScreenSaverShowAdapter(
ScreenSaverShowA.this, bmps);
viewPager.setAdapter(adapter);
}
}
/** 图片定时自动切换 */
private void autoSwitch() {
int interval = 3000;
Timer timer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
Message message = new Message();
handler.sendMessage(message);
}
};
timer.schedule(task, interval, interval);
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
int currentPage = viewPager.getCurrentItem();
int tempNum = bmps.length == 0 ? drawables.length : bmps.length;
int nextPage = (currentPage + 1) % tempNum;
viewPager.setCurrentItem(nextPage);
super.handleMessage(msg);
}
};
class OnClick implements OnClickListener {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
ScreenSaverShowA.this.finish();
}
}
}
总结和注意:
1.系统屏保的屏蔽方法以及屏幕唤醒的知识参考API就可以了,比较简单的新知识
2.如果很多张图片来加载的话,很可能出现令人最头疼的OOM,由于屏保就需求全屏显示,所以图片缩放的方式不合适,没想到好办法。不过为了避免反复解锁过程中出现OOM,在onDestroy()方法中对图片进行了recycle。
3.在模拟器上运行没有发现问题,但可能在不同的机型上会出现问题,比如有些手机将安卓的源码改掉了,甚至不允许使用屏蔽系统屏保的方法。还是原生态的android系统最好了,都瞎改什么呢。
相关推荐
下面,我们将详细探讨与Android屏幕锁相关的知识点。 1. **Android权限管理**:在Android中,访问和修改屏幕状态需要特定的权限。例如,`android.permission.DISABLE_KEYGUARD`用于禁用键盘锁定,而`android....
通过对这份源码的深入学习,开发者不仅可以掌握如何实现一个基本的Android屏幕锁,还能了解到Android系统级别的交互方式、数据存储策略以及用户体验设计。这对于提升Android开发技能,尤其是涉及安全和用户界面设计...
下面我们将深入探讨Android屏幕锁的相关知识点。 1. **Android权限与安全模型** 在开发Android屏幕锁应用时,首先要考虑的是权限问题。例如,可能需要`SYSTEM_ALERT_WINDOW`权限来在锁屏界面上显示自定义视图,...
以下是对Android屏幕锁相关知识点的详细说明: 1. **Android权限**:在Android系统中,屏幕锁通常需要读取和写入系统设置的权限,以便修改或读取锁屏状态。例如,`android.permission.WRITE_SETTINGS` 和 `android....
本文将深入探讨Android屏幕锁定的相关知识点,包括其工作原理、实现机制以及如何进行自定义设置。 一、Android锁屏概述 1.1 锁屏模式 Android提供了多种锁屏模式供用户选择,包括无锁、图案锁、PIN码锁、密码锁和...
这个压缩包"实用源码——Android屏幕锁源码.rar"提供了一套完整的Android屏幕锁定应用的源代码,可以帮助开发者深入理解屏幕锁的实现原理,并可以作为开发自定义屏幕锁的参考。以下是基于这个主题的详细知识点讲解:...
本文将深入探讨Android屏幕密码锁的实现原理,并以"NumberLock"为例,解析其源码,帮助开发者理解如何创建自定义的数字密码锁。 首先,屏幕密码锁的基本组件包括锁屏界面、密码验证逻辑以及与系统服务的交互。锁屏...
下面我们将深入探讨这个主题,了解Android屏幕锁的工作原理及其相关知识点。 一、Android系统架构 Android操作系统是基于Linux内核的开源移动平台,它由多个层次组成,包括Linux内核、硬件抽象层(HAL)、库、...
下面我们将深入探讨基于安卓Android的屏幕锁实现机制、涉及的关键技术以及如何通过源码学习相关知识。 1. 屏幕锁定机制: 安卓系统提供了多种屏幕锁定方式,如图案、PIN码、密码和指纹等。这些屏幕锁功能主要由系统...
首先,我们要了解Android屏幕锁的类型。在Android系统中,屏幕锁主要有PIN码、图案、密码和指纹等几种形式。这些锁屏方式为用户提供了不同级别的安全性,以保护设备不被未经授权的访问。 1. **权限申请**: 在...
在Android系统中,屏幕锁是保护用户隐私和设备安全的重要机制。这个压缩包"Android源码实用源码屏幕锁源码.zip"包含了实现一个自定义屏幕锁的源代码,这对于我们深入理解Android安全机制和自定义组件开发具有很大的...
在Android平台上,开发一款一键锁屏应用是一项常见的任务,它能帮助用户快速便捷地锁定设备屏幕,节省电量并保护隐私。本项目名为“android一键锁屏源代码,android4.2工作正常”,意味着它适用于Android 4.2(果冻...
"保护电源键不求人,android开发一键锁屏源码 直接编译"这个项目提供了一个实用的解决方案,允许开发者和爱好者无需依赖电源键就能快速锁定设备屏幕。下面,我们将深入探讨这个主题,并基于提供的源码进行解析。 ...
在学习这个示例的过程中,你不仅需要理解Android的权限管理机制,还需要熟悉BroadcastReceiver、IntentFilter、Service以及系统服务(如KeyguardManager)的使用。同时,为了提供良好的用户体验,你还需考虑错误处理...
在Android平台上,开发一款一键锁屏应用可以帮助用户快速便捷地锁定屏幕,节省电量,保护隐私。本文将深入探讨“android一键锁屏源码”的相关知识点,包括其工作原理、实现方式以及可能遇到的问题。 首先,我们需要...
Android屏幕锁源码可能包括了Activity(活动)、Service(服务)、BroadcastReceiver(广播接收者)和ContentProvider(内容提供者)等组件的实现,以及与Android系统安全框架的交互,如KeyguardManager(锁屏管理器...
学习和理解这些代码,开发者不仅可以提升对Android系统底层运作的理解,还能掌握如何创建更安全、更个性化的锁屏体验,以及如何在必要时正确执行恢复出厂设置,以保护用户数据和设备安全。这在开发面向公众的应用...