基于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  ..
<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,这下终于是彻底完成了大笑


原创粉丝点击