Android需求2
设置中增加一个一级菜单显示内存信息,进入后的界面可自己定义,显示当前已用内存和手机总内存,同时还有一个按钮,点击按钮清理掉除设置外的所有后台应用。
系统内置的方法的获取内存的方法
- 在
strings.xml
中的total_memory
属性 ,发现又系统方法获取内存,通过全局搜索total_memory
- 发现
process_stats_summary
的有一项的 title是total_memory
- 对
process_stats_summary
进行R.xml.process_stats_summary
全局搜索- 发现
ProcessStatsSummary.java
进行了调用,路径为com.android.settings.applications
,里面是获取内存的方法
手机总内存和已用内存的实现
-
在
top_level_setting.xml
中添加一级菜单,代码如下:<PreferenceScreen> ... ... <Preference android:fragment="com.android.settings.memory.MemoryFragment" android:icon="@drawable/ic_phone_info" android:key="top_memory_info" android:order="40" android:title="@string/memory_info" android:summary="@string/read_memory_summary" /> </PreferenceScreen>
-
在
com.android.settings
目录下新建一个包memory
,并在该包下新建一个类MemoryFragment
,该类继承SettingsPreferenceFragment
使用
ActivityManager
类来获取内存信息:ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
manager.getMemoryInfo(memoryInfo);总内存: memoryInfo.totalMem
可用内存: memoryInfo.availMem
package com.android.settings.memory; import android.app.ActivityManager; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.RemoteException; import android.text.format.Formatter; import android.util.Log; import android.app.settings.SettingsEnums; import android.widget.Toast; import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.applications.ProcStatsData.MemInfo; import com.android.settings.applications.ProcessStatsBase; import java.util.List; public class MemoryFragment extends SettingsPreferenceFragment { private static final String TAG = "MemoryFragment"; private Context context; private static final String KEY_TOTAL_MEMORY = "my_total_memory"; private static final String KEY_USED_MEMORY = "my_used_memory"; private Preference mTotalMemory; private Preference mUsedMemory; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); addPreferencesFromResource(R.xml.memory_info_show); mTotalMemory = findPreference(KEY_TOTAL_MEMORY); mUsedMemory = findPreference(KEY_USED_MEMORY); showMemory(); } public void showMemory(){ // Get Memory information ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); manager.getMemoryInfo(memoryInfo); String totalMemory = Formatter.formatShortFileSize(context, memoryInfo.totalMem); String availMemory = Formatter.formatShortFileSize(context, memoryInfo.availMem); Log.d(TAG, "totalMemory: " + totalMemory + "<==> availMemory==> " + availMemory); //Assign memory information to the control mTotalMemory.setSummary(totalMemory); mUsedMemory.setSummary(availMemory); } @Override public int getMetricsCategory() { return SettingsEnums.PROCESS_STATS_SUMMARY; } @Override public int getHelpResource() { return 0; } @Override public void onAttach(Context context) { super.onAttach(context); this.context = context; } }
-
在
xml
包下 新建一个二级目录布局文件 ,名为memory_info_show.xml
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:settings="http://schemas.android.com/apk/res-auto" android:key="customize_menu" android:title="@string/memory_menu"> <Preference android:key="my_total_memory" android:title="@string/total_memory" android:icon="@drawable/ic_emergency_gesture_24dp" android:order="100"/> <Preference android:key="my_used_memory" android:title="@string/used_memory" android:icon="@drawable/ic_emergency_gesture_24dp" android:order="150" /> </PreferenceScreen>
-
在
strings.xml
中添加标题内容<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- Memory Title --> <string name="memory_menu">Memory for Phone</string> <!-- Show Memory info --> <string name="memory_info">Show Memory</string> <!-- Memory Summary --> <string name="read_memory_summary">Memory</string> <!-- Used Memory --> <string name="used_memory">Used Memory</string> ... ... </resources>
-
效果实现
杀死除自己外的其他后台应用
清除多任务后台 Recents(多任务)
Android 9.0 与Android 8.1 中的点击Recent键清除按钮有些区别,之前Android 8.1 的全部清除按钮位于SystemUI中,而Android 9.0 的“全部清除”按钮位于Launcher3中;
**Android 获取上下文几个方法的区别 **
- getContext(): 这是View的一个方法,获取视图上下文,view一般是依托于Activity,所以这个方法返回的是当前Activity实例,一般在Activity中可以使用 YourActivityName.this代替。
- getApplicationContext(): 这个是获取整个生命周期的上下文,一般用于application中,获取app相关的基础信息。
- getBaseContext(): 是ContextWrapper中的方法,基本不用,Google也不推荐使用,是一种委托,在一个context获取另一个context。
- getApplication(): 这个是获取当前进程的Application实例,可以去操作自己写的Application中的方法。
SystemUI
的参考资料 : https://www.jianshu.com/p/2e0f403e5299
SystemUI
源码分析 :https://blog.csdn.net/u011164827/article/details/102998091
SystemUI
中recents
实现流程分析 :https://blog.csdn.net/wcsbhwy/article/details/118893801
SystemUI
的功能划分一般为以下几个部分
StatusBar
(状态栏):通知消息提示和状态展示NavigationBar
(导航栏):返回,HOME,RecentKeyGuard
(键盘锁):锁屏模块Recents
:近期应用管理,以堆叠的形式展示Notification Panel
(通知面板):展示系统或应用的通知内容,提供快速系统设置开关Volume
:展示或控制音量的变化:媒体、铃音、通知、通话音量ScreenShot
(截屏):长按电源键+音量下键后截屏,用以展示截取的屏幕照片/内容PowerUI
:主要处理和Power相关的事件。RingtonePlayer
:铃音播放StackDivider
:控制管理分屏PipUI
:画中画管理(Android7.0)
工具使用 :在SDK目录下,
sdk/tools/bin/uiautomatorviewer.bat
文件 , 双击打开文件 ,待进入UI Automator Viewer
,手机打开某个页面[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HFMFBnC6-1655341417191)(E:\Typora–pictures\image-20220608150049720.png)]
清除任务后台除设置外
通过
ActivtyManager
来进行获取和移除任务栈 参考资料:https://blog.csdn.net/hacker_crazy/article/details/78365406
https://blog.csdn.net/hacker_crazy/article/details/78399303
https://blog.csdn.net/liu149339750/article/details/8111462
-
在二级布局文件
memory_info_show.xml
中增加一个Preference来设置一个点击事件my_clear_background
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:settings="http://schemas.android.com/apk/res-auto" android:key="customize_menu" android:title="@string/memory_menu"> <Preference android:key="my_total_memory" android:title="@string/total_memory" android:icon="@drawable/ic_emergency_gesture_24dp" android:order="100" /> <Preference android:key="my_used_memory" android:title="@string/used_memory" android:icon="@drawable/ic_emergency_gesture_24dp" android:order="150" /> <Preference android:key="my_clear_background" android:icon="@drawable/btn_clear_bg" android:title="@string/clear_title" android:summary="@string/clear_summary" android:order="160"/> </PreferenceScreen>
-
在实现类中
MemoryFragment.java
类中,获取控件的key,并为其添加点击事件,并通过ActivityManager
类来进行获取开启的任务栈,并进行判断,移除任务栈,方法public void killAllAppsExceptionSettings()
package com.android.settings.memory; import android.app.ActivityManager; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.RemoteException; import android.text.format.Formatter; import android.util.Log; import android.app.settings.SettingsEnums; import android.widget.Toast; import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.applications.ProcStatsData.MemInfo; import com.android.settings.applications.ProcessStatsBase; import java.util.List; public class MemoryFragment extends SettingsPreferenceFragment implements Preference.OnPreferenceClickListener { private static final String TAG = "MemoryFragment"; private Context context; private static final String KEY_TOTAL_MEMORY = "my_total_memory"; private static final String KEY_USED_MEMORY = "my_used_memory"; private static final String KEY_CLEAR_BACKGROUND = "my_clear_background"; private Preference mTotalMemory; private Preference mUsedMemory; private Preference mClearBackground; private long freeMemory; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); addPreferencesFromResource(R.xml.memory_info_show); mTotalMemory = findPreference(KEY_TOTAL_MEMORY); mUsedMemory = findPreference(KEY_USED_MEMORY); mClearBackground = findPreference(KEY_CLEAR_BACKGROUND); showMemory(); mClearBackground.setOnPreferenceClickListener(this); } public void showMemory(){ // Get Memory information ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); manager.getMemoryInfo(memoryInfo); // Get Total Memory , Avail Memory and used Memory String totalMemory = Formatter.formatShortFileSize(context, memoryInfo.totalMem); String availMemory = Formatter.formatShortFileSize(context, memoryInfo.availMem); // 获取已用的内存大小 String usedMemory= Formatter.formatShortFileSize(context, (memoryInfo.totalMem - memoryInfo.availMem)); Log.d(TAG, "totalMemory: " + totalMemory + "<==> availMemory==> " + availMemory + "<==> usedMemory " + usedMemory ); // 获取当前的可用内存 freeMemory = memoryInfo.availMem; //Assign memory information to the control mTotalMemory.setSummary(totalMemory); mUsedMemory.setSummary(availMemory); } @Override public int getMetricsCategory() { return SettingsEnums.PROCESS_STATS_SUMMARY; } @Override public int getHelpResource() { return 0; } @Override public void onAttach(Context context) { super.onAttach(context); this.context = context; } // 清除除设置应用外其他所有后台应用 public void killAllAppsExceptionSettings(){ int MAX_TASKS = 100; // 获取Activity管理类 ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); // 获取用户最近使用过的应用程序信息集合,第一个参数:最大值,第二个参数:ActivityManager.RECENT_IGNORE_UNAVAILABL /** * RecentTaskInfo 类,主要的字段 * Intent baseIntent 得到能跳转这个Task的Activity,即能通过这个Intent启动这个Intent指向的程序。 * int id 得到这个Task的标识,如果是-1,则标识这个程序没有启动,其他数字表示启动了。 * int persistentId 任务的唯一值 */ List<ActivityManager.RecentTaskInfo> recentTasks = am.getRecentTasks(MAX_TASKS, ActivityManager.RECENT_IGNORE_UNAVAILABLE); Log.d(TAG, "recentTasks.size = " + recentTasks.size()); // 进行一个循环遍历,并通过比较,筛选出不需要移除的哪一项,并忽略 for (ActivityManager.RecentTaskInfo recentInfo : recentTasks) { Intent intent = new Intent(recentInfo.baseIntent); if (recentInfo.origActivity != null) { intent.setComponent(recentInfo.origActivity); } if (!intent.getComponent().getClassName().equals("com.android.settings.Settings")){ Log.d(TAG, "forceStopPackage ==> " + intent.getComponent().getPackageName() + " <== className ==> " + intent.getComponent().getClassName()); am.killBackgroundProcesses(intent.getComponent().getPackageName()); //RemoveTask.removeTask(mContext, recentInfo.persistentId); try { // 清除最近的任务 Remove a task by id ActivityManager.getService().removeTask(recentInfo.persistentId); } catch (RemoteException e) { Log.w(TAG, "Failed to remove task=" +recentInfo.persistentId); } } } } @Override public boolean onPreferenceClick(Preference preference) { Log.d(TAG, "onPreferenceClick: " + preference.getKey() ); ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); manager.getMemoryInfo(memoryInfo); // 计算当前的释放的内存 String nowMemory = Formatter.formatShortFileSize(context , (freeMemory - memoryInfo.availMem)); Log.d(TAG,"Last Memory ==> " + nowMemory); switch (preference.getKey()){ case "my_clear_background": //SendBroadcast(); killAllAppsExceptionSettings(); Toast.makeText(context, "Clear All Apps Success!! Free Memory: " + nowMemory, Toast.LENGTH_SHORT).show(); break; } return false; } }
-
实现效果
在Settings中的二级菜单中,点击Clear按钮,实现清除后台所有任务,除Settings外