如何第一次写Android Launcher Switcher就上手 android怎么在launcher前启动一个应用程序

\u521a\u63a5\u89e6android\u4e0d\u4e45\uff0c\u8981\u5f00\u53d1launcher\uff0c\u5e94\u8be5\u600e\u6837\u5165\u624b

SDK\u91cc\u9762\u6709\u4e2a\u793a\u4f8b\u53eb"Home",\u6216\u8005\u76f4\u63a5\u4e0b\u8f7d\u6e90\u7801,\u770b\u91cc\u9762\u7684Launcher

\u5982\u679c\u4f60\u8981\u5b9a\u5236\u4e00\u4e2aAndroid\u7cfb\u7edf\uff0c\u4f60\u60f3\u7528\u4f60\u81ea\u5df1\u7684Launcher(Home)\u4f5c\u4e3b\u754c\u9762\u6765\u66ff\u6362Android\u81ea\u5e26\u7684Home\uff0c\u800c\u4e14\u4e0d\u5e0c\u671b\u7528\u6237\u5b89\u88c5\u7684Launcher\u6765\u66ff\u6362\u6389\u4f60\u7684Launcher\uff0c\u5e94\u8be5\u5982\u4f55\u6765\u5b9e\u73b0\u5462\uff1f
\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u4fee\u6539Framework\u5c42\u6765\u5b9e\u73b0\u8fd9\u6837\u7684\u529f\u80fd\u3002

1) \u9996\u5148\u4e86\u89e3\u4e00\u4e0bAndroid\u7684\u542f\u52a8\u8fc7\u7a0b\u3002
Android\u7cfb\u7edf\u7684\u542f\u52a8\u5148\u4eceZygote\u5f00\u59cb\u542f\u52a8\uff0c\u7136\u540e......(\u4e2d\u95f4\u7684\u8fc7\u7a0b\u5c31\u4e0d\u8bf4\u4e86).....\u4e00\u76f4\u5230\u4e86SystemServer(framework)\u8fd9\u4e2a\u5730\u65b9\uff0c\u770b\u5230\u8fd9\u6bb5\u4ee3\u7801\uff1a

/**
* This method is called from Zygote to initialize the system. This willcause the native
* services (SurfaceFlinger, AudioFlinger, etc..) to be started. Afterthat it will call back
* up into init2() to start the Android services.
*/
native public static void init1(String[] args);

public static void main(String[] args) {
if (SamplingProfilerIntegration.isEnabled()) {
SamplingProfilerIntegration.start();
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
SamplingProfilerIntegration.writeSnapshot("system_server");
}
}, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
}

// The system server has to run all of the time, so it needs to be
// as efficient as possible with its memory usage.
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

System.loadLibrary("android_servers");
init1(args);
}

public static final void init2() {
Log.i(TAG, "Entered the Android system server!");
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}
}

\u4eceSystemServer\u7684main\u51fd\u6570\u5f00\u59cb\u542f\u52a8\u5404\u79cd\u670d\u52a1\uff1a
\u9996\u5148\u542f\u52a8init1,\u7136\u540e\u542f\u52a8init2.\u4ece\u4e0a\u9762\u7684\u6ce8\u91ca\u53ef\u4ee5\u770b\u5230\uff1ainit1\u8fd9\u4e2a\u65b9\u6cd5\u65f6\u88abZygote\u8c03\u7528\u6765\u521d\u59cb\u5316\u7cfb\u7edf\u7684\uff0cinit1\u4f1a\u542f\u52a8native\u7684\u670d\u52a1\u5982SurfaceFlinger,AudioFlinger\u7b49\u7b49\uff0c\u8fd9\u4e9b\u5de5\u4f5c\u505a\u5b8c\u4ee5\u540e\u4f1a\u56de\u8c03init2\u6765\u542f\u52a8Android\u7684service\u3002

\u8fd9\u91cc\u6211\u4eec\u4e3b\u8981\u6765\u5173\u6ce8init2\u7684\u8fc7\u7a0b\u3002init2\u4e2d\u542f\u52a8ServerThread\u7ebf\u7a0b\uff0cServerThread\u4e2d\u542f\u52a8\u4e86\u4e00\u7cfb\u5217\u7684\u670d\u52a1\uff0c\u6bd4\u5982\u8fd9\u4e9b\uff1a

ActivityManagerService
EntropyService
PowerManagerService
TelephonyRegistry
PackageManagerService
AccountManagerService
BatteryService
HardwareService
Watchdog
SensorService
BluetoothService
StatusBarService
ClipboardService
InputMethodManagerService
NetStatService
ConnectivityService
AccessibilityManagerService
NotificationManagerService
MountService
DeviceStorageMonitorService
LocationManagerService
SearchManagerService
FallbackCheckinService
WallpaperManagerService
AudioService
BackupManagerService
AppWidgetService

\u8fd9\u4e9b\u5927\u5927\u5c0f\u5c0f\u7684\u670d\u52a1\u8d77\u6765\u4ee5\u540e\uff0c\u5f00\u59cb
((ActivityManagerService)ActivityManagerNative.getDefault()).systemReady()
\u5728systemReady\u540e\u5f00\u59cb\u5f00\u59cb\u542f\u52a8Launcher\u3002\u5728\u5bfb\u627eLauncher\u7684\u65f6\u5019\u662f\u6839\u636eHOME\u7684filter\uff08\u5728Manifest\u4e2d\u5b9a\u4e49\u7684\uff09\u6765\u8fc7\u6ee4\u3002
\u7136\u540e\u6839\u636efilter\u51fa\u6765\u7684HOME\u6765\u542f\u52a8\uff0c\u5982\u679c\u53ea\u6709\u4e00\u4e2aHOME\uff0c\u5219\u542f\u52a8\u8fd9\u4e2aHOME\uff0c\u5982\u679c\u7528\u6237\u81ea\u5df1\u88c5\u4e86HOME\uff0c\u90a3\u5c31\u4f1a\u5f39\u51fa\u6765\u4e00\u4e2a\u5217\u8868\u4f9b\u7528\u6237\u9009\u62e9\u3002

\u6211\u4eec\u73b0\u5728\u5e0c\u671b\u4ece\u8fd9\u91cc\u5f39\u51fa\u6211\u4eec\u81ea\u5df1\u5b9a\u5236\u7684Launcher,\u540c\u65f6\u4e5f\u4e0d\u5e0c\u671b\u5f39\u51fa\u9009\u62e9HOME\u7684\u754c\u9762\uff0c\u6211\u4eec\u4e0d\u5e0c\u671b\u7528\u6237\u4fee\u6539\u6211\u4eec\u7684home\uff0c\u6bd4\u5982\u6211\u4eec\u7684home\u4e0a\u653e\u4e86\u597d\u591a\u5e7f\u544a\uff0c\u4ee5\u53ca\u5f3a\u5236\u5b89\u88c5\u7684\u7a0b\u5e8f\uff0c\u4e0d\u5e0c\u671b\u7528\u6237\u628a\u5b83\u5e72\u6389\u3002

\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u8fd9\u6837\u6765\u5b9e\u73b0\uff1a

2) \u5b9a\u4e49\u4e00\u4e2a\u79c1\u6709\u7684filter\u9009\u9879\uff0c\u7136\u540e\u7528\u8fd9\u4e2a\u9009\u9879\u6765\u8fc7\u6ee4HOME.
\u4e00\u822c\u60c5\u51b5\u4e0b\u6211\u4eec\u4f7f\u7528Manifest\u4e2d\u5b9a\u4e49\u7684<categoryandroid:name="android.intent.category.HOME"\u6765\u8fc7\u6ee4\u7684\uff0c\u6211\u4eec\u73b0\u5728\u589e\u52a0\u4e00\u4e2a\u79c1\u6709\u7684HOME_FIRST\u8fc7\u6ee4\u3002

\u5728Intent.java(frameworks/base/core/java/android/content/Intent.java)\u4e2d\u6dfb\u52a0\u4e24\u884c\u4ee3\u7801

//lixinso:\u6dfb\u52a0CATEGORY_FS_HOME
@SdkConstant(SdkConstantType.INTENT_CATEGORY)
public static final String CATEGORY_FS_HOME= "android.intent.category.FS_HOME";

3\uff09\u4fee\u6539\u548cCATEGORY_HOME\u76f8\u5173\u7684\u6240\u6709\u7684\u5730\u65b9\uff0c\u90fd\u6539\u6210CATEGORY_FS_HOME\uff0c\u4e3b\u8981\u662fframework\u4e2d\u7684\u8fd9\u51e0\u4e2a\u5730\u65b9\uff1a\u4f7f\u7528grep\u547d\u4ee4\u67e5\u627e\u8981\u4fee\u6539\u7684\u5730\u65b9\uff1a

grep CATEGORY_HOME -l * -R



\u5c06\u4e0a\u8ff0\u6587\u4ef6\u4e2d\u548cCATEGORY_HOME\u76f8\u5173\u7684\u6240\u6709\u7684\u5730\u65b9\uff0c\u90fd\u6539\u6210CATEGORY_FS_HOME\u3002
4) \u5199\u4e00\u4e2a\u81ea\u5df1\u7684Launcher.
\u53ef\u4ee5\u53c2\u8003android sample\u4e2d\u7684Launcher\uff0c\u6216\u8005android\u6e90\u4ee3\u7801\u4e2d\u7684 /packages/apps/Launcher \u6765\u5199\u3002
\u5728Launcher\u4e2d\u6807\u8bb0\u5176\u662f\u4e0d\u662fLauncher\u7684\u6700\u5173\u952e\u7684\u4ee3\u7801\u65f6Manifest\u4e2d\u7684filter:android:name="android.intent.category.HOME"
\u73b0\u5728\u6211\u4eec\u5b9a\u4e49\u4e86\u81ea\u5df1\u7684filter,\u90a3\u4e48\uff0c\u6211\u4eec\u5728\u6211\u4eec\u81ea\u5df1\u5199\u7684Launcher\u4e2d\u5c06Manifest\u6539\u4e3a\uff1a

<activity android:name=".FirstAppActivity"
android:label="@string/app_name">









\u7136\u540e\u5c06\u7f16\u8bd1\u597d\u7684apk\u653e\u5230\u65b9\u5f0ffs100_root/system/app\u76ee\u5f55\u4e0b\u3002

5)\u5c06Android\u81ea\u5e26\u7684Launcher\u5220\u9664\u6389
\u5305\u62ec\u6e90\u4ee3\u7801(packages/apps/Launcher)\u548capk(/out/target/product/generic/system/app/Launcher.apk)\u3002

6) \u91cd\u65b0\u7f16\u8bd1Android
\u505a\u5b8c\u8fd9\u4e9b\u5de5\u4f5c\uff0c\u5c31\u53ef\u4ee5\u91cd\u65b0\u7f16\u8bd1Android\u4e86\uff0c\u6211\u4eec\u53ef\u4ee5\u7f16\u8bd1\u4fee\u6539\u8fc7\u7684\u51e0\u4e2a\u76f8\u5173\u7684\u5305\uff0c\u53ef\u4ee5\u7528mmm\u547d\u4ee4\u6765\u7f16\u8bd1\u90e8\u5206\u7684\u6539\u52a8\u3002\u8fd9\u91cc\u9700\u8981\u8fd9\u6837\u7f16\u8bd1\uff1a

$ source build/envsetup.sh
$ lunch
$ mmm frameworks/base
$ mmm frameworks/base/services/java
$ mmm frameworks/policies/base/mid
$ mmm frameworks/policies/base/phone


\u91cd\u65b0\u542f\u52a8\u5f00\u53d1\u677f\uff0c\u4ece\u5f00\u53d1\u677f\u4e0a\u5c31\u53ef\u4ee5\u770b\u5230\u542f\u52a8\u7684Launcher\u662f\u6211\u4eec\u81ea\u5df1\u7684Launcher\uff0c\u4e0d\u4f1a\u51fa\u73b0\u9ed8\u8ba4\u7684Launcher\u4e86\uff0c\u4e5f\u4e0d\u4f1a\u51fa\u73b0\u9009\u62e9\u754c\u9762\u3002

9)\u6211\u4eec\u518d\u9a8c\u8bc1\u4e00\u4e0b\uff0c\u5982\u679c\u7528\u6237\u88c5\u4e0a\u4e86\u4e00\u4e2a\u5176\u4ed6\u7684Launcher(Home)\u4f1a\u600e\u4e48\u6837\u3002
\u4ece\u7f51\u4e0a\u627e\u4e00\u4e2a\u4e00\u822c\u7684Launcher\u6216\u8005\u81ea\u5df1\u5199\u4e00\u4e2a\u4e00\u822c\u7684Launcher\u88c5\u4e0a\u53bb\uff0c\u91cd\u65b0\u542f\u52a8\uff0c\u4e0d\u4f1a\u51fa\u73b0\u9009\u62e9\u754c\u9762\u3002
\u6309HOME\u952e\u4e5f\u4e0d\u4f1a\u51fa\u6765\u4e24\u4e2aHOME\u6765\u9009\u62e9\u3002


\u8fd9\u6837\u6211\u4eec\u5c31\u7262\u7262\u63a7\u5236\u4e86\u7528\u6237\u7684\u684c\u9762\u3002
\u53ea\u6709\u6211\u4eec\u81ea\u5df1\u5b9a\u5236\u7684HOME\u624d\u80fd\u88c5\u4e0a\u3002\u8fd9\u5bf9\u4e8e\u5b9a\u5236Android\u8bbe\u5907\u7684\u5382\u5546\u5f88\u6709\u7528\u5904\u3002

  Home App and Switcher thereof

  有玩 Android 系统手机的人应该都有使用过 Android Launcher 之类的应用程式,它是用於变换桌面环境或操作的应用程式,或可以说是变更使用者经验 (UX) 的程式。在命名上我个人是比较偏好称作 Home App,因为它是按下 Home 键切换或执行的程式,而且它也是跑在 home screen 的桌面程式;而 Launcher 的狭定义是来自 Android 官方预设的 Home app,即 Launcher.apk。我自己下载 Android source Froyo,里面预设是 Launcher2.apk (com.android.launcher2),位於 {SourceDir}/packages/apps 下。

  Activity 可以在 AndroidManifest.xml 中注册启动器,启动器也就是 launcher,它不代表是 Launcher.apk 或任何一种 Home App,而是指应用程式进入口会显示在 Home App (或 Launcher)上。而 Home App 一般来说都没有注册启动器,因此有人就写了侦测系统中所有 Home App 的程式,也就是 Home App Switcher。比较好的 Swicher 还会提供清除和设定 default Home App。我在 HTC Incredible S 中安装了数种 Home App,即 Launcher7、ADW、Zeam、Regina、LauncherPro、Home Sample、Home++,当然预设的 HTC Sense 也有。其中只有 Zeam 是有注册 launcher 分类,所以在应用程式选单上就能找得到。

  Intent and Intent Filters

  在 Android 系统中,Intent 是极为重要,也是最基本要知道的东西。对於系统而言,Intent 就像是应用程式的描述,也类似标签的概念。根据 Intent 内容,系统或应用程式能够去使用与搜寻其他应用程式与其提供的服务。Intent 资讯是注册在程式的 AndroidManifest.xml,并包含在 Intent Filters 标签的内容中。当搜寻系统中的应用程式时,会去比对应用程式的 Intent Filters,而搜寻条件是包装在 Intent 物件中以找到符合某种条件程式。Intent Filters 的内容就像是应用程式的索引,内容比对成功就会回传相对应的 ResolveInfo。有关 Intent 的详细内容可以参考底下提供的官方网页连结 [1]。

  一个 Activity 基本上要在 AndroidManifest.xml 的 intent-filter 中注册一个 action 和 category; action预设是 intent.ACTION_MAIN,而 category 预设是 intent.CATEGORY_LAUNCHER。根据官方网站说明,ACTION_MAIN 指该 Activity 是个可开始启动的进入点;CATEGORY_LAUNCHER 指该 Activity 在 Home App 上有启动器,也就是在应用程式选单上会出现该 Activity 的 icon,以方便执行。注册内容如下:

  <activity android:name=".HomeSelector" 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 都注册 CATEGORY_LAUNCHER,那在安装完後就会有多个 icon 出现在程式选单上,分别能执行各个 Activity。如果 Activity 没有注册 CATEGORY_LAUNCHER,那至少要注册 CATEGORY_DEFAULT,因为它是系统使用 Intent 搜寻的预设条件之一。注册 CATEGORY_DEFAULT 後该 Activity 不会有 icon 在应用程式选单上出现,所以一般都是给非 ACTION_MAIN 的 Activity 注册,如 intent.ACTION_VIEW 之类的。如果 Activity 只注册 action,一般预设 Intent 的搜寻可能会失效,那就需要使用显形式启动,以上面的例子来看,就是指定启动 HomeSelector,例子如下:

  view sourceprint?
  1 Intent i = new Intent(this, HomeSelector.class);

  2 startActivity(i);
  如果是指定启动外部程式,那可以按照下面的做法:

  view sourceprint?
  1 Intent myIntent = new Intent();

  2 myIntent.setClassName("com.KaDaNet", "com.KaDaNet.KaDaNet_MainController");

  3 startActivity(myIntent);
  那隐含式搜寻呢?如果你有 Android SDK 有研究,那你应该看过 SDK 中的 sample code,其中的 API Demo 展示了许多使用 API 功能的 Activity,而 API Demo 是由阶层式列表对这些 Activity 分类。这个阶层式列表的内容是动态生成出来的,由 loadLabel 和 activityInfo.name 去分类。因为是动态生成,所以就不会把列表写死,那所有列表上要显示的 Activity 资讯,就是利用隐含式搜寻获得,程式码如下:

  view sourceprint?
  1 Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);

  2 mainIntent.addCategory(Intent.CATEGORY_SAMPLE_CODE);

  3 PackageManager pm = getPackageManager();

  4 List<resolveinfo> list = pm.queryIntentActivities(mainIntent, 0);
  API Demo 只显示 category 注册为 CATEGORY_SAMPLE_CODE 的 Activity 的资讯。把条件塞进 Intent 後利用 queryIntentActivities 搜寻,其中的一个 Activity 注册内容如下:

  <activity android:name=".app.CustomDialogActivity"
  android:label="@string/activity_custom_dialog"
  android:theme="@style/Theme.CustomDialog">
  <intent-filter>
  <action android:name="android.intent.action.MAIN" />
  <category android:name="android.intent.category.SAMPLE_CODE" />
  </intent-filter>
  </activity>

  Home App and Intent Filters

  在 Android 中,Home App 需要告诉系统自己是一个 Home App,那它才会以 Home 的方式去执行,也就是跑在 home screen 上。同样的,Home App 透过在 AndroidManifest.xml 上注册 category 为 intent.CATEGORY_HOME 就可以了。以 SDK sample 中的 Home 为例,其注册内容如下:

  <activity android:name="Home" android:theme="@style/Theme"
  android:launchMode="singleInstance"
  android:stateNotNeeded="true">
  <intent-filter>
  <action android:name="android.intent.action.MAIN" />
  <category android:name="android.intent.category.HOME"/>
  <category android:name="android.intent.category.DEFAULT" />
  </intent-filter>
  </activity>

  搜寻 Home App 的做法与 API Demo 相同,使用 PackageManager 中的 queryIntentActivities 即可。在下面范例中,对搜寻到的结果取出我们想要的资讯包装成 HomeInfo,并回传 List。

  view sourceprint?
  01 private List<homeinfo> queryHomeApp() {

  02 Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);

  03 mainIntent.addCategory(Intent.CATEGORY_HOME);

  04 PackageManager pm = getPackageManager();

  05 List<resolveinfo> rList = pm.queryIntentActivities(mainIntent, 0);

  06 List<homeinfo> homeList = new ArrayList<homeinfo>();

  07

  08 for(ResolveInfo r : rList) {

  09 homeList.add(new HomeInfo(r, pm));

  10 }

  11 return homeList;

  12 }
  

  这里使用 HomeInfo 类别包装四种资讯,即类别名称、封包名称、Activity 标签和 Activity icon。

  view sourceprint?
  01 public class HomeInfo {

  02 public String name;

  03 public String packageName;

  04 public String label;

  05 public Drawable icon;

  06

  07 public HomeInfo(ResolveInfo rInfo, PackageManager pm) {

  08 name = rInfo.activityInfo.name;

  09 packageName = rInfo.activityInfo.packageName;

  10 label = rInfo.loadLabel(pm).toString();

  11 icon = rInfo.loadIcon(pm);

  12 }

  13 }
  很简单吧!这样就能取得系统中所有的 Home App 资讯,接下来根据这些资讯来切换 Home App。切换的方式,先前也提到过了,那就是显形式启动!

  view sourceprint?
  1 public void switchHome(String packageName) {

  2 Intent homeIntent = new Intent("android.intent.action.MAIN");

  3 homeIntent.addCategory("android.intent.category.HOME");

  4 homeIntent.addCategory("android.intent.category.DEFAULT");

  5 homeIntent.setPackage(packageName);

  6 this.startActivity(homeIntent);

  7 this.finish();

  8 }
  在程式界面上显示所有已安装的 Home App 资讯,最简单的方式是利用 ListView,再新建一个 list adapter 进行配接并设定 list item 按下後要处理的事,以上面的程式码来看就是我们要处理的事,即切换到另一个 Home App。界面设定的程式码如下,显示画面如 Fig. 1。

  view sourceprint?
  01 ListView lvHome = (ListView) findViewById(R.id.lvHome);

  02 final HomeListAdapter hAdapter = new HomeListAdapter(this);

  03 hAdapter.addItemList(queryHomeApp());

  04 lvHome.setAdapter(hAdapter);

  05 lvHome.setOnItemClickListener(new AdapterView.OnItemClickListener() {

  06 @Override

  07 public void onItemClick(AdapterView parent, View view, int position, long id) {

  08 HomeListItem item = (HomeListItem) hAdapter.getItem(position);

  09 switchTo(item.getHomeInfo().packageName);

  10 }

  11 });

  Fig.1. Home App list

  Home App Management

  一个较好的 Home App 切换器都会提供相关管理的功能。一般来说,基本的管理功能就是显示资讯。除了找出系统中的所有 Home App 之外,也要能够显示这些 Home App 相关的资讯,当然资讯的种类要依需求而定。以 Home App 来说,可以分成未执行和执行时的资讯,也就是说使用者或许希望能看到哪些 Home App 是正在执行;如果正在执行,还有额外的资讯可以看到,像是程序相关的资料。根据这些资讯可以让使用者决定是否要切换或是关掉 Home App。在这节中,我将介绍如何获知该 Home App 是否正在执行,与执行时所占用记忆体的多寡,当然也包括移除 Home App 安装和显示应用程式细节。

  Android 中的 ActivityManager 类别 [2] 是用来与系统里正在执行的程序进行互动的 API;使用这个类别,我们能拿到所有正在执行的 App,并能以特定的 package 名称去过滤某个 App 是否正在执行,范例如下:

  view sourceprint?
  1 public boolean isAppRunning() {

  2 for(RunningAppProcessInfo info : mAM.getRunningAppProcesses()) {

  3 if (info.processName.equals(packageName)) return true;

  4 for (String pn : info.pkgList) {

  5 if (pn.equals(packageName)) return true;

  6 }

  7 }

  8 return false;

  9 }
  函式中的 mAM 即 ActivityManager,利用 getRunningAppProcesses 方法取得所有的存活 App,因为 Android 并没有提供过滤的功能,需要自行处理;其中先比对程序名称是因为在一般的情况下,很多 App 的程序名称会与 package 名称相同,所以用这种方式加速比对。如果该 Home App 的 package 名称与程序名称不相同,只好比对这程序中所有被载进的 package 其名称。

  接下来是取得程序所占用的记忆体,利用 ActivityManager 中的 getProcessMemoryInfo 并餵入程序 ID 即可得到 Debug.MemoryInfo。RunningAppProcessInfo 的栏位包含程序 ID,可以透过刚刚取得的执行中 App 资料获得。不过实际上,程序所占用的记忆体情况挺复杂的,可以参考 [3-6]。RSS 指包含整个分享函式库。PSS 是以等比例去切割分享函式库大小,比例分母为所有使用到该函式库的程序数。这边我仅以程序全部的 PSS 来估计记忆体占用,程式码如下:

  view sourceprint?
  1 public int getMemoryUsed(ActivityManager am) {

  2 Debug.MemoryInfo mInfo = am.getProcessMemoryInfo(new int[]{PID})[0];

  3 return mInfo.getTotalPss();

  4 }
  使用者可能会根据 Home App 占用记忆体的多寡来决定是否要停止该程序,以移出更多的空间给其他比较需要资源的软体使用。移除程序的 API 为用 ActivityManager 类别中的 killBackgroundProcesses 方法,使用它需要跟系统注册 KILL_BACKGROUND_PROCESSES 权限,使用方法如下,只消 package 名称:

  view sourceprint?
  1 mAM.killBackgroundProcesses(pkgName);
  停止某 Home App 之後,Home Selector 需要更新画面上的 ListView,这只要通知 ListView 的资料源更新即可,Android 有提供了 notifyDataSetChanged 这个方便的函式。不过要注意的是这个函式只是去通知更新,也就是说 Adapter 的 getView 会重新执行一遍,如果资料绑定处理不是写在 getView 中就不会发生资料更新,而需要在更新通知前先处理资料绑定。

  view sourceprint?
  1 public void refresh() {

  2 hAdapter.notifyDataSetChanged();

  3 }
  剩下的移除安装和检视应用程式细节功能也很简单,都是透过 Intent 去启动系统的 Activity,特别要注意的是设定 Intent 的 flag 和目标 URI,程式码如下:

  view sourceprint?01 public void startHomeInfo(Context cont, String pkgName) {

  02 Uri homeURI = getHomeUri(pkgName);

  03 Intent i = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, homeURI);

  04 i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

  05 cont.startActivity(i);

  06 }

  07

  08 public void unInstallHome(Context cont, String pkgName) {

  09 Uri homeURI = getHomeUri(pkgName);

  10 Intent i = new Intent(Intent.ACTION_DELETE, homeURI);

  11 i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

  12 cont.startActivity(i);
}
  13

扩展阅读:android苹果版下载 ... 安卓app下载安装android ... 苹果android怎么设置 ... android怎么打开 ... 手机android权限限制 ... android系统怎么开启 ... android服务下载安装 ... android在哪里打开 ... android文件访问限制 ...

本站交流只代表网友个人观点,与本站立场无关
欢迎反馈与建议,请联系电邮
2024© 车视网