Android中獲取正在執行的服務-------ActivityManager.RunningServiceInfo的使用(三)

yangxi_001發表於2016-01-29

轉自:http://blog.csdn.net/qinjuning/article/details/7015313

        關於PackageManager和ActivityManager的使用 ,自己也寫了一些DEMO 了,基本上寫的線路參考了Settings模組下的應用程式,大家如果真正的有所興趣,建議大家看看原始碼,不過醜化說在前面,我自己也沒怎麼看過這方面的原始碼,只在需要的時候,才跑過去翻翻。

        今天,在耐著最後一點性子,寫下了這篇博文,基本上完成了整個應用程式功能模組的介紹,大家也在此係列上慢慢擴充。


ActivityManager.RunningServiceInfo類:  封裝了正在執行的服務資訊

獲取系統裡所有真正執行的服務是通過呼叫ActivityManager方法來得到的,具體方法如下:

 

List<ActivityManager.RunningServiceInfo> getRunningServices (int maxNum)

功能:返回所有正在執行的服務

引數:   maxNum 代表我們希望返回的服務數目大小,一般給個稍大的值即可, 例如,50 。 

                               

ActivityManager.RunningServiceInfo 類

  常用欄位:

 

               long   activeSince        服務第一次被啟用的時間, 包括啟動和繫結方式

               int      clientCount          如果該Service是通過Bind方法方式連線,則clientCount代表了service連線客戶端的數目

               int      crashCount          服務執行期間,出現當機的次數

               boolean   foreground   若為true,則該服務在後臺執行

               int        pid                          如果不為0,表示該service所在的程式ID號( PS:為0的話我也不清楚 - - 求指點)

               int        uid                          使用者ID 類似於Linux的使用者許可權,例如root等                    

              String   process                 程式名,預設是包名或者由屬性android:process指定

              ComponentName  service          獲得該Service的元件資訊 包含了pkgname / servicename資訊

 

PackageManger類

   說明: 封裝了對應用程式資訊的操作

        獲得應用程式資訊的的方法如下:

          public abstractApplicationInfo  getApplicationInfo(String  packageName, int flags)

                 引數:packagename 包名

                             flags 該ApplicationInfo是此flags標記,通常可以直接賦予常數0即可

                 功能:返回ApplicationInfo物件

 

        關於PackageManger更多資訊,請檢視<Android中獲取應用程式(包)的資訊-----PackageManager的使用(一)>

 

   Task任務的使用,我也就不在贅述了,大家可以仔細看下SDK,在此推薦一篇部落格來幫助大家理解。

          《Android系統的程式,任務,服務的資訊

 

 

Demo說明:

 

         我們獲取了系統里正在執行的服務資訊,包括包名,圖示,service類名等。為了達到Settings下應用程式模組中的

    正在執行服務的效果,我們點選某一服務後,理論上來說是可以停止該服務的,但是由於許可權permissions不夠,可能報

    SecurityException異常,導致應用程式發生異常。

 

    關於許可權不夠的問題,可以分為兩種:

       1、 在AndroidManifest.xml檔案中,為<activity/>或<service/>節點指定android:permission屬性時,在其他程式中操作時,

              需要 宣告該permission許可權 。 具體可以參考下面這篇文章:

                                              《android 自定義許可權 permission》

 

       2、 系統許可權,這個我們就沒什麼話說了。 可以參考下面這篇文章。

                                   android.uid.system 獲取系統許可權 》

 

    截圖如下:(加上了水印,請諒解)

 

                                                 

 

 

     老規矩,資原始檔不在貼了。 主工程邏輯如下:

[java] view plain copy
 print?
  1. package com.qin.runservice;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.Collections;  
  5. import java.util.Comparator;  
  6. import java.util.List;  
  7.   
  8. import android.app.Activity;  
  9. import android.app.ActivityManager;  
  10. import android.app.AlertDialog;  
  11. import android.app.Dialog;  
  12. import android.content.ComponentName;  
  13. import android.content.Context;  
  14. import android.content.DialogInterface;  
  15. import android.content.Intent;  
  16. import android.content.pm.ApplicationInfo;  
  17. import android.content.pm.PackageManager;  
  18. import android.content.pm.PackageManager.NameNotFoundException;  
  19. import android.os.Bundle;  
  20. import android.os.Debug;  
  21. import android.util.Log;  
  22. import android.view.ContextMenu;  
  23. import android.view.Menu;  
  24. import android.view.MenuItem;  
  25. import android.view.View;  
  26. import android.view.ContextMenu.ContextMenuInfo;  
  27. import android.widget.AdapterView;  
  28. import android.widget.ListView;  
  29. import android.widget.TextView;  
  30. import android.widget.AdapterView.OnItemClickListener;  
  31.   
  32. public class BrowseRunningServiceActivity extends Activity implements  
  33.         OnItemClickListener {  
  34.   
  35.     private static String TAG = "RunServiceInfo";  
  36.   
  37.     private ActivityManager mActivityManager = null;  
  38.     // ProcessInfo Model類 用來儲存所有程式資訊  
  39.     private List<RunSericeModel> serviceInfoList = null;  
  40.   
  41.     private ListView listviewService;  
  42.     private TextView tvTotalServiceNo;  
  43.   
  44.     public void onCreate(Bundle savedInstanceState) {  
  45.         super.onCreate(savedInstanceState);  
  46.   
  47.         setContentView(R.layout.browse_service_list);  
  48.   
  49.         listviewService = (ListView) findViewById(R.id.listviewService);  
  50.         listviewService.setOnItemClickListener(this);  
  51.   
  52.         tvTotalServiceNo = (TextView) findViewById(R.id.tvTotalServiceNo);  
  53.   
  54.         // 獲得ActivityManager服務的物件  
  55.         mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);  
  56.   
  57.         // 獲得正在執行的Service資訊  
  58.         getRunningServiceInfo();  
  59.         // 對集合排序  
  60.         Collections.sort(serviceInfoList, new comparatorServiceLable());  
  61.   
  62.         System.out.println(serviceInfoList.size() + "-------------");  
  63.   
  64.         // 為ListView構建介面卡物件  
  65.         BrowseRunningServiceAdapter mServiceInfoAdapter = new   
  66.                  BrowseRunningServiceAdapter(BrowseRunningServiceActivity.this, serviceInfoList);  
  67.   
  68.         listviewService.setAdapter(mServiceInfoAdapter);  
  69.   
  70.         tvTotalServiceNo.setText("當前正在執行的服務共有:" + serviceInfoList.size());  
  71.     }  
  72.     // 獲得系統正在執行的程式資訊  
  73.     private void getRunningServiceInfo() {  
  74.   
  75.         // 設定一個預設Service的數量大小  
  76.         int defaultNum = 20;  
  77.         // 通過呼叫ActivityManager的getRunningAppServicees()方法獲得系統裡所有正在執行的程式  
  78.         List<ActivityManager.RunningServiceInfo> runServiceList = mActivityManager  
  79.                 .getRunningServices(defaultNum);  
  80.   
  81.         System.out.println(runServiceList.size());  
  82.   
  83.         // ServiceInfo Model類 用來儲存所有程式資訊  
  84.         serviceInfoList = new ArrayList<RunSericeModel>();  
  85.   
  86.         for (ActivityManager.RunningServiceInfo runServiceInfo : runServiceList) {  
  87.   
  88.             // 獲得Service所在的程式的資訊  
  89.             int pid = runServiceInfo.pid; // service所在的程式ID號  
  90.             int uid = runServiceInfo.uid; // 使用者ID 類似於Linux的許可權不同,ID也就不同 比如 root等  
  91.             // 程式名,預設是包名或者由屬性android:process指定  
  92.             String processName = runServiceInfo.process;   
  93.   
  94.             // 該Service啟動時的時間值  
  95.             long activeSince = runServiceInfo.activeSince;  
  96.   
  97.             // 如果該Service是通過Bind方法方式連線,則clientCount代表了service連線客戶端的數目  
  98.             int clientCount = runServiceInfo.clientCount;  
  99.   
  100.             // 獲得該Service的元件資訊 可能是pkgname/servicename  
  101.             ComponentName serviceCMP = runServiceInfo.service;  
  102.             String serviceName = serviceCMP.getShortClassName(); // service 的類名  
  103.             String pkgName = serviceCMP.getPackageName(); // 包名  
  104.   
  105.             // 列印Log  
  106.             Log.i(TAG, "所在程式id :" + pid + " 所在程式名:" + processName + " 所在程式uid:"  
  107.                     + uid + "\n" + " service啟動的時間值:" + activeSince  
  108.                     + " 客戶端繫結數目:" + clientCount + "\n" + "該service的元件資訊:"  
  109.                     + serviceName + " and " + pkgName);  
  110.   
  111.             // 這兒我們通過service的元件資訊,利用PackageManager獲取該service所在應用程式的包名 ,圖示等  
  112.             PackageManager mPackageManager = this.getPackageManager(); // 獲取PackagerManager物件;  
  113.   
  114.             try {  
  115.                 // 獲取該pkgName的資訊  
  116.                 ApplicationInfo appInfo = mPackageManager.getApplicationInfo(  
  117.                         pkgName, 0);  
  118.   
  119.                 RunSericeModel runService = new RunSericeModel();  
  120.                 runService.setAppIcon(appInfo.loadIcon(mPackageManager));  
  121.                 runService.setAppLabel(appInfo.loadLabel(mPackageManager) + "");  
  122.                 runService.setServiceName(serviceName);  
  123.                 runService.setPkgName(pkgName);  
  124.                 // 設定該service的元件資訊  
  125.                 Intent intent = new Intent();  
  126.                 intent.setComponent(serviceCMP);  
  127.                 runService.setIntent(intent);  
  128.   
  129.                 runService.setPid(pid);  
  130.                 runService.setProcessName(processName);  
  131.   
  132.                 // 新增至集合中  
  133.                 serviceInfoList.add(runService);  
  134.   
  135.             } catch (NameNotFoundException e) {  
  136.                 // TODO Auto-generated catch block  
  137.                 System.out.println("--------------------- error -------------");  
  138.                 e.printStackTrace();  
  139.             }  
  140.   
  141.         }  
  142.     }  
  143.   
  144.     // 觸控可停止  
  145.     @Override  
  146.     public void onItemClick(AdapterView<?> arg0, View arg1, int position,  
  147.             long arg3) {  
  148.         // TODO Auto-generated method stub  
  149.         final Intent stopserviceIntent = serviceInfoList.get(position)  
  150.                 .getIntent();  
  151.   
  152.         new AlertDialog.Builder(BrowseRunningServiceActivity.this).setTitle(  
  153.                 "是否停止服務").setMessage(  
  154.                 "服務只有在重新啟動後,才可以繼續執行。但這可能會給電子市場應用程式帶來意想不到的結果。")  
  155.                 .setPositiveButton("停止"new DialogInterface.OnClickListener() {  
  156.   
  157.                     @Override  
  158.                     public void onClick(DialogInterface dialog, int which) {  
  159.                         // TODO Auto-generated method stub  
  160.                         // 停止該Service  
  161.                         //由於許可權不夠的問題,為了避免應用程式出現異常,捕獲該SecurityException ,並彈出對話方塊  
  162.                         try {  
  163.                             stopService(stopserviceIntent);  
  164.                         } catch (SecurityException sEx) {  
  165.                             //發生異常 說明許可權不夠   
  166.                             System.out.println(" deny the permission");  
  167.                             new AlertDialog.Builder(BrowseRunningServiceActivity.this).setTitle(  
  168.                             "許可權不夠").setMessage("對不起,您的許可權不夠,無法停止該Service").create().show();  
  169.                         }  
  170.                         // 重新整理介面  
  171.                         // 獲得正在執行的Service資訊  
  172.                         getRunningServiceInfo();  
  173.                         // 對集合排序  
  174.                         Collections.sort(serviceInfoList, new comparatorServiceLable());  
  175.                         // 為ListView構建介面卡物件  
  176.                         BrowseRunningServiceAdapter mServiceInfoAdapter = new BrowseRunningServiceAdapter(  
  177.                                 BrowseRunningServiceActivity.this,  
  178.                                 serviceInfoList);  
  179.                         listviewService.setAdapter(mServiceInfoAdapter);  
  180.                         tvTotalServiceNo.setText("當前正在執行的服務共有:"  
  181.                                 + serviceInfoList.size());  
  182.                     }  
  183.   
  184.                 }).setNegativeButton("取消",  
  185.                         new DialogInterface.OnClickListener() {  
  186.   
  187.                             @Override  
  188.                             public void onClick(DialogInterface dialog,  
  189.                                     int which) {  
  190.                                 // TODO Auto-generated method stub  
  191.                                 dialog.dismiss(); // 取消對話方塊  
  192.                             }  
  193.                         }).create().show();  
  194.     }  
  195.   
  196.     // 自定義排序 根據AppLabel排序  
  197.     private class comparatorServiceLable implements Comparator<RunSericeModel> {  
  198.   
  199.         @Override  
  200.         public int compare(RunSericeModel object1, RunSericeModel object2) {  
  201.             // TODO Auto-generated method stub  
  202.             return object1.getAppLabel().compareTo(object2.getAppLabel());  
  203.         }  
  204.   
  205.     }  
  206.   
  207. }  


         程式碼下載地址:http://download.csdn.net/detail/qinjuning/3846097

     

         終於完成了這幾塊功能的介紹,這些功能的具體使用都挺類似的,最重要的是看你有沒有耐心去把他們做出來。

   作為一個小小程式設計師,我還是一步一步來做吧。。

 

相關文章