基于DreamService的屏保
来源:互联网 发布:python explode 编辑:程序博客网 时间:2024/04/30 23:18
DreamService是android已经出了很久的的特性,在设备闲置、充电或锁屏时,可以显示特定的内容。但是网上的资源不多,我自己开发了一个,希望对大家有些帮助。
实现起来很简单,首先注册
<service android:name=".DayDreamService" android:exported="true" android:icon="@drawable/ic_launcher" android:label="ScreenSaver" android:permission="android.permission.BIND_DREAM_SERVICE" > <intent-filter> <action android:name="android.service.dreams.DreamService"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </service>
一开始我使用的是ViewPager+Fragment的方式来实现,因为之前有过这样的开发,所以很容易就将思路向这里走了,但是后来经过实践发现DreamService里是实现不了Fragment的,至少我没办法实现如果有能够通过ViewPager+Fragment的方式实现的大神希望能留言学习下。
所以我就只好通过ViewPager来实现了。
public class DayDreamService extends DreamService {private final static String TAG = "DayDreamService";private ViewPager viewPager;private List<ImageView> imageViews;private int currentItem = 0;private MyAdapter pageAdapter;boolean nowAction = false;// 当前用户正在滑动视图String[] fileName = new String[0];AssetManager manager;private String[] imageUrls=null;private ScheduledExecutorService scheduledExecutorService;ImageLoader imageLoader;@Overridepublic void onAttachedToWindow() {super.onAttachedToWindow();setInteractive(false);setFullscreen(true);setContentView(R.layout.mydream);configImageLoader();init();}//退出的时候干掉自己哈哈哈哈@Overridepublic void onDetachedFromWindow(){super.onDetachedFromWindow();viewPager = null;manager = null;imageLoader = null;imageViews = null;scheduledExecutorService=null;imageUrls=null;fileName=null;pageAdapter=null;System.exit(0);android.os.Process.killProcess(android.os.Process.myPid());Log.d(TAG, "onDetachedFromWindow");}@SuppressLint("HandlerLeak")private Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {viewPager.setCurrentItem(currentItem);};};//获取目录下的图片的绝对路径@SuppressWarnings("finally")public String[] getImageName(Context context, String loc) {String prefix = "";try {if (loc.equalsIgnoreCase("screen")) {manager = context.getAssets();fileName = manager.list(loc);prefix = "assets://screen/";} else {File f = new File(loc);fileName = f.list();prefix = "file:///data/local/tmp/image/";}} catch (IOException e) {e.printStackTrace();} finally {if(fileName!=null){for (int i = 0; i < fileName.length; i++) {fileName[i] = prefix + fileName[i];}}return fileName;}}@Overridepublic void onDreamingStarted() {scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();//20秒换一图scheduledExecutorService.scheduleAtFixedRate(new ScrollTask(), 20, 20, TimeUnit.SECONDS);super.onDreamingStarted();}private class ScrollTask implements Runnable {public void run() {synchronized (viewPager) {if (!nowAction) {System.out.println("currentItem: " + currentItem);currentItem = currentItem + 1;handler.obtainMessage().sendToTarget();}}}}private class MyPageChangeListener implements OnPageChangeListener {public void onPageSelected(int position) {currentItem = position;}public void onPageScrollStateChanged(int arg0) {if (arg0 == 0) {nowAction = false;}if (arg0 == 1) {nowAction = true;}if (arg0 == 2) {}}public void onPageScrolled(int arg0, float arg1, int arg2) {}}public void init() {//首先获取/data/local/tmp/image/目录下的图片,如果没有就获取screen里的默认图片imageUrls = getImageName(this, "/data/local/tmp/image/");if (imageUrls==null||imageUrls.length==0) {imageUrls = getImageName(this, "screen");}imageViews = new ArrayList<ImageView>();for (int i = 0; i < imageUrls.length; i++) {// ImageView imageView = new ImageView(this);ImageView imageView = (ImageView) LayoutInflater.from(this).inflate(R.layout.view_banner, null);ImageLoader.getInstance().displayImage(imageUrls[i], imageView);// imageView.setImageResource(imageResId[i]);imageView.setScaleType(ScaleType.CENTER_CROP);imageViews.add(imageView);}viewPager = (ViewPager) findViewById(R.id.vp);pageAdapter = new MyAdapter();viewPager.setCurrentItem(Integer.MAX_VALUE / 4);viewPager.setAdapter(pageAdapter);// 切换动画实现淡入淡出效果viewPager.setPageTransformer(true, new DepthPageTransformer());// 设置滑动切换时间try {Field mScroller = null;mScroller = ViewPager.class.getDeclaredField("mScroller");mScroller.setAccessible(true);FixedSpeedScroller scroller = new FixedSpeedScroller(viewPager.getContext());scroller.setScrollDuration(1500);mScroller.set(viewPager, scroller);} catch (NoSuchFieldException e) {} catch (IllegalArgumentException e) {} catch (IllegalAccessException e) {}viewPager.setOnPageChangeListener(new MyPageChangeListener());}//ViewPager的Adapterprivate class MyAdapter extends PagerAdapter {@Overridepublic int getCount() {//定义一个极大的数,实现伪无线循环return Integer.MAX_VALUE / 2;}@Overridepublic Object instantiateItem(View arg0, int position) {View view = null;if (position % imageViews.size() < 0) {view = imageViews.get(imageViews.size() + position);} else {view = imageViews.get(position % imageViews.size());}ViewParent vp = view.getParent();if (vp != null) {ViewGroup parent = (ViewGroup) vp;parent.removeView(view);}((ViewPager) arg0).addView(view);return view;}@Overridepublic void destroyItem(View arg0, int arg1, Object arg2) {}@Overridepublic boolean isViewFromObject(View arg0, Object arg1) {return arg0 == arg1;}}//configImageLoader框架,用来管理和处理图片private void configImageLoader() {// 初始化ImageLoader@SuppressWarnings("deprecation")DisplayImageOptions options = new DisplayImageOptions.Builder().showStubImage(R.drawable.ic_launcher) // 设置图片下载期间显示的图片// .showImageForEmptyUri(R.drawable.ic_launcher) //// 设置图片Uri为空或是错误的时候显示的图片.showImageOnFail(R.drawable.icon) // 设置图片加载或解码过程中发生错误显示的图片.bitmapConfig(Bitmap.Config.RGB_565) // 图片太多的时候设置 ,避免内存溢出和解码失败//.cacheInMemory(true) // 设置下载的图片是否缓存在内存中//.cacheOnDisc(true) // 设置下载的图片是否缓存在SD卡中// .displayer(new RoundedBitmapDisplayer(20)) // 设置成圆角图片.build(); // 创建配置过得DisplayImageOption对象ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext()).defaultDisplayImageOptions(options).threadPriority(Thread.NORM_PRIORITY - 2).denyCacheImageMultipleSizesInMemory().discCacheFileNameGenerator(new Md5FileNameGenerator()).tasksProcessingOrder(QueueProcessingType.LIFO).build();ImageLoader.getInstance().init(config);}}
其中有几个工具类
/** * 自定义高度的viewpapger */public class BaseViewPager extends ViewPager {private boolean scrollable = true;public BaseViewPager(Context context) {super(context);}public BaseViewPager(Context context, AttributeSet attrs) {super(context, attrs);}/** * 设置viewpager是否可以滚动 * * @param enable */public void setScrollable(boolean enable) {scrollable = enable;}@Overridepublic boolean onInterceptTouchEvent(MotionEvent event) {if (scrollable) {return super.onInterceptTouchEvent(event);} else {return false;}}}
/** * 自定义的淡入淡出效果 */public class DepthPageTransformer implements BaseViewPager.PageTransformer { private static final float MIN_ALPHA = 0.0f; //最小透明度 @SuppressLint("NewApi")public void transformPage(View view, float position) { int pageWidth = view.getWidth(); //得到view宽 if (position < -1) { // [-Infinity,-1) // This page is way off-screen to the left. 出了左边屏幕 view.setAlpha(0); } else if (position <= 1) { // [-1,1] if (position < 0) { //消失的页面 view.setTranslationX(-pageWidth * position); //阻止消失页面的滑动 } else { //出现的页面 view.setTranslationX(pageWidth); //直接设置出现的页面到底 view.setTranslationX(-pageWidth * position); //阻止出现页面的滑动 } // Fade the page relative to its size. float alphaFactor = Math.max(MIN_ALPHA, 1 - Math.abs(position)); //透明度改变Log view.setAlpha(alphaFactor); } else { // (1,+Infinity] // This page is way off-screen to the right. 出了右边屏幕 view.setAlpha(0); } } }
/** * 自定义的Scroller */public class FixedSpeedScroller extends Scroller {private int mDuration = 1000;public void setScrollDuration(int duration){ this.mDuration = duration; } public FixedSpeedScroller(Context context) {super(context);// TODO Auto-generated constructor stub}public FixedSpeedScroller(Context context, Interpolator interpolator) {super(context, interpolator);}@Overridepublic void startScroll(int startX, int startY, int dx, int dy, int duration) {// Ignore received duration, use fixed one insteadsuper.startScroll(startX, startY, dx, dy, mDuration);}@Overridepublic void startScroll(int startX, int startY, int dx, int dy) {// Ignore received duration, use fixed one insteadsuper.startScroll(startX, startY, dx, dy, mDuration);}public void setmDuration(int time) {mDuration = time;}public int getmDuration() {return mDuration;}}
xml ..
最后向assets里面建立个screen文件夹,里面放上几张图就ok了大功告成。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#00FFFFFF" android:orientation="vertical" > <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" > <android.support.v4.view.ViewPager android:id="@+id/vp" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout></LinearLayout>
最后向assets里面建立个screen文件夹,里面放上几张图就ok了大功告成。
但是一运行发现应用的内存占用太大了,就循环播几张图片而已,居然要整整50+m的内存,真是醉了,估摸着是android-support-v4.jar 和 universal-image-loader-1.9.2-SNAPSHOT-with-sources.jar 两个的问题,干脆就不用ViewPager和configImageLoader了,自己思考了一下需求,只是个图片的轮播罢了,直接就是一个ImageView,然后一个Handler不断的替换图片就ok了,由于DreamService只要一操作,就回退出屏保状态,所以就无所谓按键控制了。没必要搞那么多幺蛾子不是吗。
public class DayDreamService extends DreamService {private final static String TAG = "DayDreamService";private int currentItem = 0;String[] fileName = new String[0];AssetManager manager;private String[] imageUrls = null;AssetManager assetManager = null;ImageView imageView = null;Bitmap oldbmp = null;int time = 20 * 1000;// 切图时间Boolean flag = false;// 是否加载的是默认图片@Overridepublic void onAttachedToWindow() {super.onAttachedToWindow();setInteractive(false);setFullscreen(true);setContentView(R.layout.mydream);Log.d(TAG, "qidong");init();}@Overridepublic void onDetachedFromWindow() {super.onDetachedFromWindow();manager = null;imageUrls = null;fileName = null;System.exit(0);android.os.Process.killProcess(android.os.Process.myPid());}@SuppressWarnings("finally")public String[] getImageName(Context context, String loc) {String prefix = "";try {if (loc.equalsIgnoreCase("screen")) {manager = context.getAssets();fileName = manager.list(loc);// prefix = "assets://screen/";prefix = "screen/";} else {File f = new File(loc);fileName = f.list();prefix = "/data/local/tmp/image/";f = null;}} catch (IOException e) {e.printStackTrace();} finally {if (fileName != null) {for (int i = 0; i < fileName.length; i++) {fileName[i] = prefix + fileName[i];}}return fileName;}}@Overridepublic void onDreamingStarted() {super.onDreamingStarted();}public void init() {imageUrls = getImageName(this, "/data/local/tmp/image/");if (imageUrls == null || imageUrls.length == 0) {flag = true;imageUrls = getImageName(this, "screen");}fileName = null;imageView = (ImageView) findViewById(R.id.iv_pb);assetManager = this.getAssets();setimage();handler.postDelayed(task, time);}public void setimage() {// 把历史的ImageView 图片对象(imageView)释放BitmapDrawable bitmapDrawable = (BitmapDrawable) imageView.getBackground();if (bitmapDrawable != null) {Bitmap hisBitmap = bitmapDrawable.getBitmap();if (hisBitmap.isRecycled() == false) {hisBitmap.recycle();}}// 设置自动清理的参数使得Bitmap占用的内存不再是1280*720*4而是1280*720*2 一下子就减了一半BitmapFactory.Options options = new BitmapFactory.Options();options.inPreferredConfig = Bitmap.Config.RGB_565;// 切换图片try {Bitmap bmp = null;if (flag) {InputStream in = assetManager.open(imageUrls[currentItem % imageUrls.length]);bmp = BitmapFactory.decodeStream(in, null, options); //要是内存还是占用太大就就直接自己改分辨率吧,会降低清晰度,但是大大减小内存// bmp=decodeSampledBitmapFromResource(in, 768,432);} else {Log.d(TAG, "uri:" + imageUrls[currentItem % imageUrls.length]);InputStream in = new FileInputStream(imageUrls[currentItem % imageUrls.length]);bmp = BitmapFactory.decodeStream(in,null,options);// bmp=decodeSampledBitmapFromResource(in, 960,540);}if (oldbmp == null) {oldbmp = bmp;}Drawable[] layers = new Drawable[2];layers[0] = new BitmapDrawable(oldbmp);layers[1] = new BitmapDrawable(bmp);oldbmp = bmp;if (currentItem == 0) {imageView.setImageBitmap(bmp);} else {TransitionDrawable transitionDrawable = new TransitionDrawable(layers);imageView.setImageDrawable(transitionDrawable);transitionDrawable.startTransition(400);}} catch (Exception e) {e.printStackTrace();}}private Handler handler = new Handler();private Runnable task = new Runnable() {public void run() {// TODOAuto-generated method stubhandler.postDelayed(this, time);// 设置延迟时间// 需要执行的代码currentItem++;setimage();}};/*public static Bitmap decodeSampledBitmapFromResource(InputStream is, int reqWidth, int reqHeight) {// First decode with inJustDecodeBounds=true to check dimensionsfinal BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeStream(is, null, options);// Calculate inSampleSizeoptions.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);// Decode bitmap with inSampleSize setoptions.inJustDecodeBounds = false;return BitmapFactory.decodeStream(is, null, options);}public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {// Raw height and width of imagefinal int height = options.outHeight;final int width = options.outWidth;int inSampleSize = 1;Log.d(TAG, "height:" + height + " width" + width);if (height > reqHeight || width > reqWidth) {final int halfHeight = height / 2;final int halfWidth = width / 2;while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {inSampleSize *= 2;}}Log.d(TAG, "height inSampleSize:" + inSampleSize);return inSampleSize;}*/}
他的xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#00FFFFFF" android:orientation="vertical" > <!-- <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" > <android.support.v4.view.ViewPager android:id="@+id/vp" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout> --> <ImageView android:id="@+id/iv_pb" android:layout_width="match_parent" android:layout_height="match_parent" /></LinearLayout>
再将原来1920p的图片换成1280p的之后,内存终于降到了10M,这下终于是彻底完成了。
阅读全文
2 0
- 基于DreamService的屏保
- 基于C#实现用于显示照片的屏保
- 基于手机令牌的屏保软件设计与实现
- 屏保
- 屏保
- 屏保
- 屏保对LCD的伤害
- 关于对屏保的操作
- 一个类似屏保的程序
- 自已作的屏保程序
- VC的一个屏保例子
- 基于VB算法+Picture+Timer控件制作的39种动画效果,类似屏保(完整原程序)
- 使用DX编写自己的屏保
- [VB.NET]雪花飘的屏保
- 用Qt写的简单屏保程序
- 关于屏保的解除与恢复
- mac屏保图片的路径问题
- Android下屏保程序的开发
- STC89C52MCU -- 双机通信及多机通信
- Java语言基础{Java_se(04)}-方法的重载设计(overload)-数组-数组的遍历-多 维数组-排序算法(冒泡排序)-选择排序
- matlab学习笔记
- Vue中提交表单数据
- 闲聊KMP算法
- 基于DreamService的屏保
- JS事件---DOM2级事件处理:addEventListener()、removeEventListener()、attachEvent()
- Mysql linux监控脚本分析
- 判断两个链表是否相交,若相交,求交点,若带环呢/fork继承问题
- MyBatis 一级缓存,二级缓存
- python变量以及类型(含笔记)
- VS2015动态库编程之MFC规则动态库(中)
- 数理逻辑基础概念
- 20170716——调试NRF51822蓝牙模块总结