360悬浮加速小火箭,内存清理,加速缓存

关于我

最近时间都比较的紧,处理不同项目的BUG,今天偷得半日闲,把剩下项目的一部分扔给了组长。有个问题没解决,做了两天也没完成,实在是没有办法了。也很感谢,旅行途中遇到很多有趣的人,希望他们越来越顺利。

废话少说,接入今天的主题。

需求文档

1、在主界面 显示 一个悬浮图标或者入口,点击后展示如下界面,直接开始清理,清理完成后,弹个toast提示(已清理多少空间),就退出界面了 2、【手机加速】一键加速,让你的手机顷刻间享受飞一般的速度 杀进程,杀掉除了我们自己应用必备的其他进程 3、【缓存清理】清除无用的垃圾,释放手机内存

任务分析

简单描述就是:点击桌面的小火箭(悬浮按钮)进入上面的清理界面,然后自动扫瞄文件,以及正在运行进程。扫瞄完成之后自动清理缓存,清理进程。清理完成之后,返回清理Toast,点击清理界面,自动消失,小火箭又重新出现。

开始执行代码

1、悬浮小火箭 我在项目中开启一个Service,用于时刻吸附屏幕两边、以及拖拉效果、时刻悬浮在其他应用之上。

MainActivity 我在入口里直接开始一个Service,用于管理悬浮小火箭,和悬浮窗口(就是清理界面)

public void startService(View view){

Intent intent=new Intent(this, MyFloatService.class);

startService(intent);

finish();

}

}

MyFloatService

/**

* @description 创建 service 方便管理悬浮小火箭 、悬浮窗口

* @date: 2020/4/14

* @author: a */

public class MyFloatService extends Service {

@Nullable

@Override

public IBinder onBind(Intent intent) {

return null;

}

@Override

public void onCreate() {

//用来开启FloatViewManager

FloatViewManager manager= FloatViewManager.getInstance(this);

manager.showFloatCircleView();

super.onCreate();

}

}

此处开启一个浮窗管理类FloatViewManager ,获取实例之后,直接显示桌面小火箭manager.showFloatCircleView()。

FloatViewManager

/**

* @description 悬浮管理类

* @date: 2020/4/14

* @author: a */

public class FloatViewManager {

//浮窗管理类用来管理悬浮窗的显示和隐藏。

private Context context;

private static FloatViewManager inStance;

private WindowManager wm;//通過WindowManager 來操控浮窗的顯示和隱藏。

private FloatCircleView circleView;

//初始的位置

private float startX;

private float startY;

//按下的位置

private float downX;

private float downY;

//移动后的位置

private float moveX;

private float moveY;

private WindowManager.LayoutParams params;

private FloatMenuView floatMenuView;

private GarbageClearView garbageClearView;

//小火箭circleView设置touch监听。

private View.OnTouchListener circleViewOnTouchListener=new View.OnTouchListener() {

@Override

public boolean onTouch(View v, MotionEvent event) {

switch (event.getAction()){

case MotionEvent.ACTION_DOWN:

//最后按下时的坐标。看ACTION_MOVE就会理解。

startX = event.getRawX();

startY = event.getRawY();

//按下时的坐标。

downX = event.getRawX();

downY = event.getRawY();

break;

case MotionEvent.ACTION_MOVE:

circleView.setDrageState(true);

moveX = event.getRawX();

moveY=event.getRawY();

float dx = moveX -startX;

float dy=moveY-startY;

params.x+=dx;

params.y+=dy;

wm.updateViewLayout(circleView,params);

startX=moveX;

startY=moveY;

break;

case MotionEvent.ACTION_UP:

float upx=event.getRawX();

if (upx>getScreenWidth()/2){

params.x=getScreenWidth()-circleView.width;

}else {

params.x=0;

}

circleView.setDrageState(false);

wm.updateViewLayout(circleView, params);

if (Math.abs(moveX-downX)>10){

return true;

}else {

return false;

}

default:

break;

}

return false;

}

};

private int getScreenWidth() {

return wm.getDefaultDisplay().getWidth();

}

//得到屏幕的高度。

private int getScreenHeigth() {

return wm.getDefaultDisplay().getHeight();

}

//得到状态栏的高度。

private int getStatusHeight(){

Class clazz = null;

Object object;

try {

clazz = Class.forName("com.android.internal.R$dimen");

object = clazz.newInstance();

int x = Integer.parseInt(clazz.getField("status_bar_height")

.get(object).toString());

return context.getResources().getDimensionPixelSize(x);

} catch (Exception e) {

return 0;

}

}

private FloatViewManager( Context context){

this.context=context;

wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

circleView =new FloatCircleView(context);

circleView.setOnTouchListener(circleViewOnTouchListener);

circleView.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

//Toast.makeText(, "onclick", Toast.LENGTH_SHORT).show();

//隱藏circleView,顯示菜单栏。

wm.removeView(circleView);

showFloatMenuView();

garbageClearView.startAnimation();//进入悬浮框 直接清理

floatMenuView.startAnimation();//进入悬浮框 动画

}

});

floatMenuView = new FloatMenuView(context);

garbageClearView = new GarbageClearView( context );

}

private void showFloatMenuView() {

WindowManager.LayoutParams params = new WindowManager.LayoutParams();

params.width=getScreenWidth();

params.height=getScreenHeigth()-getStatusHeight();

params.gravity= Gravity.BOTTOM|Gravity.LEFT;

params.x=0;

params.y=0;

params.type=WindowManager.LayoutParams.TYPE_TOAST;

params.flags= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;

params.format= PixelFormat.RGBA_8888;

wm.addView(floatMenuView, params);

}

public static FloatViewManager getInstance(Context context){

if (inStance==null){

synchronized(FloatViewManager.class){

if (inStance==null){

inStance=new FloatViewManager(context);

}

}

}

return inStance;

}

/**

* 展示浮窗

*/

public void showFloatCircleView(){

//参数设置

if (params==null){

params = new WindowManager.LayoutParams();

params.width=circleView.width;

params.height=circleView.heigth;

params.gravity= Gravity.TOP|Gravity.LEFT;

params.x=0;

params.y=0;

params.type=WindowManager.LayoutParams.TYPE_TOAST;

params.flags= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;

params.format= PixelFormat.RGBA_8888;

}

//先清除、防止重复创建、然后将小火箭加入窗体中。

// wm.removeView( circleView );

wm.addView(circleView, params);

}

public void hideFloatMenuView(){

wm.removeView(floatMenuView);

}

}

剩下的就是自定义View了,代码可以在文章末尾前往github白票

另外需要注意的两个点: 1、获取正在运行的进程由于google之前的ActivityManager不能适配高版本,在高版本时候只能获取前台界面(一般只能获取一个进程,就是自身)。可以使用AndroidProcesses,使用方法: 添加权限:

添加依赖库:

//获取运行进程

implementation 'com.jaredrummler:android-processes:1.0.9'

同步之后,使用如下获取正在运行List

List mProcess = AndroidProcesses.getRunningAppProcesses();

然后遍历要杀死的进程

for ( AndroidAppProcess amProcess :mProcess ){

//获取缓存

if ( amProcess.name.contains( "com.www" ) || amProcess.name.startsWith( "system" ) ) {

Log.d( TAG, "扫描不杀的进程:" + amProcess.name );

continue;

}

android.os.Debug.MemoryInfo[] memoryInfo = am

.getProcessMemoryInfo(new int[] { amProcess.pid });

int memory = memoryInfo[0].getTotalPrivateDirty();

AllMemorySize = AllMemorySize + memory;

Log.d( TAG, "扫描要杀的进程:" + amProcess.name );

}

2、清理内存 需要使用系统隐藏api 然后使用以下方法:

/**

* 使用反射方法调用系统隐藏api: deleteApplicationCacheFiles 返回清除是否成功

* */

private boolean deleteApplicationCacheFiles(String packageName) {

isCleanCacheSucceed = false;

try {

Method method = PackageManager.class.getMethod(

"deleteApplicationCacheFiles", new Class[] { String.class,

IPackageDataObserver.class });

method.invoke(pm, packageName, new IPackageDataObserver.Stub() {

@Override

public void onRemoveCompleted(String packageName,

boolean succeeded) throws RemoteException {

if(succeeded){

Log.d("DYP", "deleteApplicationCacheFiles -->> succeeded "+succeeded);

Log.d("DYP", "deleteApplicationCacheFiles -->> packageName "+packageName);

}

isCleanCacheSucceed = succeeded;

}

});

} catch (Exception e) {

// e.printStackTrace();

Log.d("DYP", "deleteApplicationCacheFiles -->> catch ");

}

return isCleanCacheSucceed;

}

实现效果