仿360一键清理实现(一)
来源:互联网 发布:安卓卫星电视软件 编辑:程序博客网 时间:2024/06/05 16:08
---------------------------------------------------------------------
编译环境:Android 4.0
测试环境:Android 4.2.2模拟器
屏幕分辨率:480*800
作者:疯狂小强
注意:
1.资源采集于网上,如有侵权请及时联系,以便处理。
2.代码仅用于学习交流,请勿商业化。
--------------------------------------------------------------------
先上部分效果图:
“一键清理”是一个桌面图标,点击图标后,显示一个视图,进行清理动画,之后显示清理了几个进程,释放了多少M内存,点击“设置过滤名单”启动另外一个Activity编辑过滤名单。
AndroidManifest.xml如下:
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.tang.demo360" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="19" /> <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/> <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.Black.NoTitleBar" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".CleanActivity" android:theme="@style/MTheme"> <intent-filter> <action android:name="android.intent.action.MAIN" /> </intent-filter> </activity> <service android:name=".CleanService"> </service> <activity android:name=".SetWhiteListActivity"></activity> </application></manifest>
1.创建快捷方式
主界面就是一个按钮,单击后,会发出一个广播com.android.launcher.action.INSTALL_SHORTCUT创建一个快捷方式,这需要权限
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
图一 图二
private void createShortcut(){ Intent shortcut = new Intent("com.android.launcher.action.INSTALL_SHORTCUT"); // 快捷方式的名字 String name = getResources().getString(R.string.app_name); shortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME,name); //不允许重复创建 shortcut.putExtra("duplicate", false); Intent shortcutIntent = new Intent(); ComponentName componentName = new ComponentName(getPackageName(), "com.tang.demo360.CleanActivity"); shortcutIntent.setComponent(componentName); shortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); ShortcutIconResource iconRes=null; //快捷方式的图标 iconRes = Intent.ShortcutIconResource.fromContext(this, R.drawable.shortcut_process_clear_shortcut_icon); shortcut.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconRes); sendBroadcast(shortcut); Log.i("AAA", "sendBroadcast : INSTALL_SHORTCUT");}
创建出来的这个快捷方式不是打开图一界面,而是打开图二的。
从createShortcut()方法代码上看
ComponentName componentName = new ComponentName(getPackageName(), "com.tang.demo360.CleanActivity");shortcutIntent.setComponent(componentName);打开了com.tang.demo360.CleanActivity这个Activity。但事实上只做了这些还不够,我们必须为CleanActivity在manifest中配置Action:
<action android:name="android.intent.action.MAIN" />这两者配合使用就可以直接启动CleanActivity了。
2.确定打开CleanActivity的位置
由效果图我们知道:快捷方式所在的位置不同CleanActivity的位置也是不同的,点击桌面快捷方式启动Activity的时候,我们打“ActivityManager”的logcat会发现如下信息:
其中:bnds=[510,282][679,399]好象是个坐标,到Launcher的源码上一看发现:
public void onClick(View v){........Object tag = v.getTag(); if (tag instanceof ShortcutInfo) { // Open shortcut final Intent intent = ((ShortcutInfo) tag).intent; int[] pos = new int[2]; v.getLocationOnScreen(pos); intent.setSourceBounds(new Rect(pos[0], pos[1], pos[0] + v.getWidth(), pos[1] + v.getHeight())); boolean success = startActivitySafely(intent, tag);......}点击快捷方式的时候的确是吧快捷方式的位置放在一个Rect中传出去了。
位置得到了接下来就只要把Activity的一些style改一下,然后把这个位置数据用上,就可以得到效果图上面的效果了
<style name="MTheme" parent="@android:style/Theme"> <item name="android:windowNoTitle">true</item> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowIsFloating">true</item> <item name="android:backgroundDimAmount">0</item> </style>android:backgroundDimAmount 调节背景灰度
android:windowIsFloating 悬浮窗口,表示浮在屏幕上的,如果在这里使用了,整个layout就会在 屏幕中心,相当于浮在屏幕上。
Rect rect = getIntent().getSourceBounds();rootView = new CleanView(this,rect);setContentView(rootView);WindowManager.LayoutParams lp = getWindow().getAttributes();WindowManager windowManager = getWindowManager();int w = windowManager.getDefaultDisplay().getWidth();int h = windowManager.getDefaultDisplay().getHeight();lp.x = lp.x+(rect.left-w/2)+Value.WIDTH/2;lp.y = lp.y+(rect.top-h/2)+Value.HEIGHT/2;getWindow().setAttributes(lp);
由于使用悬浮窗后坐标原点也在屏幕中心,和我们所得到的Rect中的参数的左边原点不同,所以需要做位置关系转化
lp.x = lp.x+(rect.left-w/2)+Value.WIDTH/2;
lp.y = lp.y+(rect.top-h/2)+Value.HEIGHT/2;
3.CleanView布局的实现
为了实现效果图上面的效果,将CleanView分成两部分
part1.xml
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/shortcut_process_clear_cover"> <ImageView android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/shortcut_process_clear_fg" /> <com.tang.demo360.view.LevelView android:id="@+id/text0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:textColor="#ffffff" android:text="10%" android:background="@drawable/task_killer"/></RelativeLayout>
part2.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:gravity="center"> <TextView android:id="@+id/text1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="清理进程0个" /> <TextView android:id="@+id/text2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="释放内存0M" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="设置过滤名单" android:background="@drawable/shortcut_process_clear_wlist"/></LinearLayout>再根据快捷方式所处的位置判断先把哪部分加入到父容器中
view = new LinearLayout(context);view.setOrientation(LinearLayout.HORIZONTAL);view.setBackgroundResource(R.drawable.shortcut_process_clear_bg);WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);int screenWidth = windowManager.getDefaultDisplay().getWidth();if(Value.WIDTH+rect.left+50>screenWidth){view.addView(view2);view.addView(view1);}else{view.addView(view1);view.addView(view2);}addView(view);
4.CleanView动画实现
出现方式:由无到有
退出方式:由有到无
清理过程动画:part1.xml ImageView不断旋转,速度由慢变快再变慢最后消失。
水面动画:先由未清理所占内存的百分比高度降低到0然后升至当前所占内存百分比的高度
前三个比较容易不做介绍,对于水面动画,在CleanView中有
public void updateView(Object [] parm){text1.setText("清理进程"+(Integer)parm[0]+"个");DecimalFormat decimalFormat=new DecimalFormat("0.0");String temp=decimalFormat.format(parm[1]);text2.setText("释放内存"+temp+"M");setLevelAnimation((Integer)parm[2]);}public void setLevelAnimation(int level){ClipDrawable clip = (ClipDrawable) text0.getBackground();text0.setText(level+"%");clip.setLevel(level*100);}
有2个方法负责快速更新以便达到动画效果。
水面的背景
<?xml version="1.0" encoding="utf-8"?> <clip xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/shortcut_process_clear_level" android:clipOrientation="vertical" android:gravity="bottom"> </clip>
使用ClipDrawable代表从其它位图上截取一个图片片段setLevel方法设置截取百分比,我在主线程中使用Timer来快速更新这个数值
timer = new Timer();
timer.schedule(task, 500, 1);
task = new TimerTask() {@Overridepublic void run() {// TODO Auto-generated method stubif(isDown){level = (level-Value.V)>=0?(level-Value.V):0;if(level ==0){isDown = false;}}else{level = (level+Value.V)<=newlevel?(level+Value.V):newlevel;}parm[2] =level/100;handler.sendEmptyMessage(Value.UPDATE_VIEW);}};
这样只要在主线程中接受Value.UPDATE_VIEW这个Message然后调用updateView()方法就可以目的动画效果。
5.我们来杀进程吧
对于这个我在网上查了一些资料写了一个工具类
CleanUtil.java
package com.tang.util;import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;import java.lang.reflect.Method;import java.util.List;import android.app.Activity;import android.app.ActivityManager;import android.content.Context;import android.util.Log;public class CleanUtil {//关闭当前运行的进程public Object [] killRunnintAppInfo(Context context) {MSaveList mSaveList = new MSaveList(context.getSharedPreferences("demo360", Activity.MODE_PRIVATE));List<String> list = mSaveList.load();ActivityManager mActivityManager = (ActivityManager) context.getSystemService(context.ACTIVITY_SERVICE);List<ActivityManager.RunningAppProcessInfo> mRunningProcess = mActivityManager.getRunningAppProcesses();int appSize = getRunningTasksSize(context);long memory = getUesdMemory(context);for (ActivityManager.RunningAppProcessInfo amProcess : mRunningProcess){if(amProcess.processName.equals("com.tang.demo360")||amProcess.processName.startsWith("system")){Log.d("AAA", "跳过不杀的进程:" + amProcess.processName);continue;}else {if(isInWhiteList(amProcess.processName,list)){Log.d("AAA", "跳过不杀的进程:" + amProcess.processName);}else{mActivityManager.killBackgroundProcesses(amProcess.processName);Log.d("AAA", "杀掉的进程:"+amProcess.processName);}}}appSize = Math.abs(appSize -getRunningTasksSize(context));memory = Math.abs(memory -getUesdMemory(context));return getRecycleMemoryInfo(context,appSize,memory);}//强制关闭进程private void forceKillApp(ActivityManager am, String packageName) {Method forceStopPackage = null;try {forceStopPackage = am.getClass().getDeclaredMethod("forceStopPackage", String.class);forceStopPackage.setAccessible(true); forceStopPackage.invoke(am, packageName);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();} }/** * 将要传出去的数据 * 杀了多少进程 * 释放多少M内存 * 当前内存百分比 * @param context * @param appSize * @param memory * @return */private Object [] getRecycleMemoryInfo(Context context,int appSize,long memory) { Object[] pram=new Object[]{0,0,0};; if(memory>=0) { pram[0] = appSize; pram[1] = (memory/1024.0); pram[2] = getUesdMemoryRate(context); } return pram; } private int getRunningTasksSize(Context context) { ActivityManager am = (ActivityManager) context.getSystemService(context.ACTIVITY_SERVICE); return am.getRunningAppProcesses().size(); } /** * 得到设备的所有RAM * @return 返回所有内存大小,单位:kb */private int getAllMemory() {String filePath = "/proc/meminfo";int ram = 0;FileReader fr = null;BufferedReader localBufferedReader = null;try {fr = new FileReader(filePath);localBufferedReader = new BufferedReader(fr, 8192);String line = localBufferedReader.readLine();int a = line.length() - 3;int b = line.indexOf(' ');String str = line.substring(b, a);while (str.substring(0, 1).equals(" ")) {str = str.substring(1, str.length());}ram = Integer.parseInt(str);} catch (IOException e) {e.printStackTrace();} finally {try {fr.close();localBufferedReader.close();} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}}return ram;}/** * 得到设备的可用RAM * @return 返回所有内存大小,单位:kb */private long getAvailMemory(Context context) {ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();am.getMemoryInfo(mi);return mi.availMem / 1024;}/** * 得到设备的已用RAM * @return 返回所有内存大小,单位:kb */private long getUesdMemory(Context context) {return getAllMemory() - getAvailMemory(context);}public int getUesdMemoryRate(Context context){return (int) (getUesdMemory(context)*100/getAvailMemory(context));}/** * 判断是否在白名单之内 * @param pkg * @param list * @return */private boolean isInWhiteList(String pkg,List<String> list){boolean inOrNot = false;if(list!=null){for(int i=0;i<list.size();i++){if(pkg.equals(list.get(i))){inOrNot = true;break;}}}return inOrNot;}}在启动CleanActivity的时候,在onCreate中启动了CleanService,热这个实现了Runnable接口
public class CleanService extends Service implements Runnable{.....@Overridepublic void run() {// TODO Auto-generated method stubhandler.sendEmptyMessage(Value.BEGIN_CLEAN);Object [] pram = cleanUtil.killRunnintAppInfo(this);Message message = new Message();message.obj = pram;message.what = Value.UPDATE;handler.sendMessage(message);}@Overridepublic void onCreate() {// TODO Auto-generated method stubif(CleanActivity.local!=null){handler = CleanActivity.local.getHandler();new Thread(this).start();cleanUtil = new CleanUtil();}super.onCreate();}....}将杀进程的工作放在后台进行。
当然杀进程也是需要权限的:
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
第一部分就这样了,第二部分分析白名单处理
由于技术水平有限,写文章的水平更是有限,如有什么错误,欢迎大牛指正。
- 仿360一键清理实现(一)
- 仿360一键清理实现(二)
- Android 一键清理、内存清理功能实现
- Android 一键清理、内存清理功能实现
- Android 一键清理、内存清理功能实现
- Android 一键清理、内存清理功能实现
- Android 一键清理、内存清理功能实现
- Android 一键清理、内存清理功能实现
- Android 一键清理、内存清理功能实现
- Android 一键清理、内存清理功能实现
- Android 一键清理、内存清理功能实现
- Android 一键清理、内存清理功能实现
- android 如何实现一键清理
- [Android开发实战]金山清理大师(猎豹清理大师)一键加速快捷方式动画实现
- 一键清理
- 一键清理 开源版
- 一键清理脚本
- 一键清理功能
- 游戏运营工作浅谈
- Java的一些理解
- git上新创建一个库->写给自己
- struts2下载文件时文件名如果包含中文出现错误
- 利用flashback query 恢复表数据
- 仿360一键清理实现(一)
- 虚函数的重载特性
- Android系统自带样式(@android:style/)
- 改变导航栏的颜色
- 根据字体多少使UILabel自动调节尺寸
- 经验总结22--抓取HTML数据,HtmlAgilityPack(续)
- sublime中的svn插件报错
- 1019. General Palindromic Number (20)
- CLR内核调试之:Malloc函数实现