服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Android - Android中获得正在运行的程序和系统服务的方法

Android中获得正在运行的程序和系统服务的方法

2021-06-19 17:34qinjuning Android

这篇文章主要介绍了Android中获得正在运行的程序和系统服务的方法,分别是对ActivityManager.RunningAppProcessInfo类和ActivityManager.RunningServiceInfo类的使用,需要的朋友可以参考下

activitymanager.runningappprocessinfo类与获取正在运行的应用程序
每一个应用程序都会运行在它独立的进程里,但是为了节省资源或者这些应用程序是为了完成某一共同工作,它们
也可能会运行在一个进程里。

Android中获得正在运行的程序和系统服务的方法

 知识点介绍:
activitymanager.runningappprocessinfo类
说明: 封装了正在运行的进程信息
常用字段:
int   pid    进程id
int   uid    进程所在的用户id
string   processname 进程名,默认是包名或者由android:process=””属性指定
string [ ]   pkglist      运行在该进程下的所有应用程序包名

demo说明:
我们利用activitymanager获取所有正在运行的进程信息后,也就是获取了每个进程里正在运行的应用程序包名(pkgname),那么通过这些包名(pkgname),直接调用packagemanager类提供的方法,可以获取这些应用程序的信息了。
一些资源文件就不贴了,直接贴出了主工程逻辑。需要注意的在这儿我们一次性获取了所有应用程序信息,然后对这些应用程序进行过滤,得到我们需要的对象。 读者可以使用packagemanager类提供的方法,进行循环遍历所有包名(pkgname),但是这样效率会比较低。
截图如下:
点击某一进程后

Android中获得正在运行的程序和系统服务的方法

查看某一进程运行的应用程序信息、所有正在运行的进程信息:

Android中获得正在运行的程序和系统服务的方法

Android中获得正在运行的程序和系统服务的方法

显示正在运行应用程序的工程代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package com.qin.ammp;
 
import java.util.arraylist;
import java.util.collections;
import java.util.hashmap;
import java.util.list;
import java.util.map;
 
import android.app.activity;
import android.app.activitymanager;
import android.content.context;
import android.content.intent;
import android.content.pm.applicationinfo;
import android.content.pm.packageinfo;
import android.content.pm.packagemanager;
import android.content.pm.packagemanager.namenotfoundexception;
import android.os.bundle;
import android.util.log;
import android.view.view;
import android.widget.adapterview;
import android.widget.listview;
import android.widget.textview;
import android.widget.adapterview.onitemclicklistener;
 
public class browserunningappactivity extends activity {
 
  private static string tag = "browserunningappactivity";
 
  private listview listview = null;
 
  private list<runningappinfo> mlistappinfo = null;
  private textview tvinfo = null ;
   
  private packagemanager pm;
 
  @override
  public void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.browse_app_list);
 
    listview = (listview) findviewbyid(r.id.listviewapp);
    tvinfo = (textview)findviewbyid(r.id.tvinfo) ;
     
    mlistappinfo = new arraylist<runningappinfo>();
 
    // 查询某一特定进程的所有应用程序
    intent intent = getintent();
    //是否查询某一特定pid的应用程序
    int pid = intent.getintextra("extra_process_id", -1);
     
    if ( pid != -1) {
      //某一特定经常里所有正在运行的应用程序
      mlistappinfo =queryspecailpidrunningappinfo(intent, pid);
    }
    else{
      // 查询所有正在运行的应用程序信息: 包括他们所在的进程id和进程名
      tvinfo.settext("所有正在运行的应用程序有-------");
      mlistappinfo = queryallrunningappinfo(); 
    }
    browserunningappadapter browseappadapter = new browserunningappadapter(this, mlistappinfo);
    listview.setadapter(browseappadapter);
  }
 
  // 查询所有正在运行的应用程序信息: 包括他们所在的进程id和进程名
  // 这儿我直接获取了系统里安装的所有应用程序,然后根据报名pkgname过滤获取所有真正运行的应用程序
  private list<runningappinfo> queryallrunningappinfo() {
    pm = this.getpackagemanager();
    // 查询所有已经安装的应用程序
    list<applicationinfo> listappcations = pm.getinstalledapplications(packagemanager.get_uninstalled_packages);
    collections.sort(listappcations,new applicationinfo.displaynamecomparator(pm));// 排序
 
    // 保存所有正在运行的包名 以及它所在的进程信息
    map<string, activitymanager.runningappprocessinfo> pgkprocessappmap = new hashmap<string, activitymanager.runningappprocessinfo>();
 
    activitymanager mactivitymanager = (activitymanager) getsystemservice(context.activity_service);
    // 通过调用activitymanager的getrunningappprocesses()方法获得系统里所有正在运行的进程
    list<activitymanager.runningappprocessinfo> appprocesslist = mactivitymanager
        .getrunningappprocesses();
 
    for (activitymanager.runningappprocessinfo appprocess : appprocesslist) {
      int pid = appprocess.pid; // pid
      string processname = appprocess.processname; // 进程名
      log.i(tag, "processname: " + processname + " pid: " + pid);
 
      string[] pkgnamelist = appprocess.pkglist; // 获得运行在该进程里的所有应用程序包
 
      // 输出所有应用程序的包名
      for (int i = 0; i < pkgnamelist.length; i++) {
        string pkgname = pkgnamelist[i];
        log.i(tag, "packagename " + pkgname + " at index " + i+ " in process " + pid);
        // 加入至map对象里
        pgkprocessappmap.put(pkgname, appprocess);
      }
    }
    // 保存所有正在运行的应用程序信息
    list<runningappinfo> runningappinfos = new arraylist<runningappinfo>(); // 保存过滤查到的appinfo
 
    for (applicationinfo app : listappcations) {
      // 如果该包名存在 则构造一个runningappinfo对象
      if (pgkprocessappmap.containskey(app.packagename)) {
        // 获得该packagename的 pid 和 processname
        int pid = pgkprocessappmap.get(app.packagename).pid;
        string processname = pgkprocessappmap.get(app.packagename).processname;
        runningappinfos.add(getappinfo(app, pid, processname));
      }
    }
 
    return runningappinfos;
 
  }
  // 某一特定经常里所有正在运行的应用程序
  private list<runningappinfo> queryspecailpidrunningappinfo(intent intent , int pid) {
 
 
    string[] pkgnamelist = intent.getstringarrayextra("extra_pkgnamelist");
    string processname = intent.getstringextra("extra_process_name");
     
    //update ui
    tvinfo.settext("进程id为"+pid +" 运行的应用程序共有 : "+pkgnamelist.length);
         
    pm = this.getpackagemanager();
   
    // 保存所有正在运行的应用程序信息
    list<runningappinfo> runningappinfos = new arraylist<runningappinfo>(); // 保存过滤查到的appinfo
 
    for(int i = 0 ; i<pkgnamelist.length ;i++){
      //根据包名查询特定的applicationinfo对象
      applicationinfo appinfo;
     try {
      appinfo = pm.getapplicationinfo(pkgnamelist[i], 0);
      runningappinfos.add(getappinfo(appinfo, pid, processname));
     }
     catch (namenotfoundexception e) {
      // todo auto-generated catch block
      e.printstacktrace();
     } // 0代表没有任何标记;
    }
    return runningappinfos ;
  }
   
   
  // 构造一个runningappinfo对象 ,并赋值
  private runningappinfo getappinfo(applicationinfo app, int pid, string processname) {
    runningappinfo appinfo = new runningappinfo();
    appinfo.setapplabel((string) app.loadlabel(pm));
    appinfo.setappicon(app.loadicon(pm));
    appinfo.setpkgname(app.packagename);
 
    appinfo.setpid(pid);
    appinfo.setprocessname(processname);
 
    return appinfo;
  }
}

activitymanager.runningserviceinfo类获取正在运行的服务
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对象
demo说明:
我们获取了系统里正在运行的服务信息,包括包名,图标,service类名等。为了达到settings下应用程序模块中的正在运行服务的效果,我们点击某一服务后,理论上来说是可以停止该服务的,但是由于权限permissions不够,可能报securityexception异常,导致应用程序发生异常。
 
关于权限不够的问题,可以分为两种:
1、 在androidmanifest.xml文件中,为<activity/>或<service/>节点指定android:permission属性时,在其他进程中操作时,需要声明该permission权限 。
2、 系统权限,这个咱就没什么话说了。
截图如下:

Android中获得正在运行的程序和系统服务的方法

主工程逻辑如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
package com.qin.runservice;
 
import java.util.arraylist;
import java.util.collections;
import java.util.comparator;
import java.util.list;
 
import android.app.activity;
import android.app.activitymanager;
import android.app.alertdialog;
import android.app.dialog;
import android.content.componentname;
import android.content.context;
import android.content.dialoginterface;
import android.content.intent;
import android.content.pm.applicationinfo;
import android.content.pm.packagemanager;
import android.content.pm.packagemanager.namenotfoundexception;
import android.os.bundle;
import android.os.debug;
import android.util.log;
import android.view.contextmenu;
import android.view.menu;
import android.view.menuitem;
import android.view.view;
import android.view.contextmenu.contextmenuinfo;
import android.widget.adapterview;
import android.widget.listview;
import android.widget.textview;
import android.widget.adapterview.onitemclicklistener;
 
public class browserunningserviceactivity extends activity implements
    onitemclicklistener {
 
  private static string tag = "runserviceinfo";
 
  private activitymanager mactivitymanager = null;
  // processinfo model类 用来保存所有进程信息
  private list<runsericemodel> serviceinfolist = null;
 
  private listview listviewservice;
  private textview tvtotalserviceno;
 
  public void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
 
    setcontentview(r.layout.browse_service_list);
 
    listviewservice = (listview) findviewbyid(r.id.listviewservice);
    listviewservice.setonitemclicklistener(this);
 
    tvtotalserviceno = (textview) findviewbyid(r.id.tvtotalserviceno);
 
    // 获得activitymanager服务的对象
    mactivitymanager = (activitymanager) getsystemservice(context.activity_service);
 
    // 获得正在运行的service信息
    getrunningserviceinfo();
    // 对集合排序
    collections.sort(serviceinfolist, new comparatorservicelable());
 
    system.out.println(serviceinfolist.size() + "-------------");
 
    // 为listview构建适配器对象
    browserunningserviceadapter mserviceinfoadapter = new
         browserunningserviceadapter(browserunningserviceactivity.this, serviceinfolist);
 
    listviewservice.setadapter(mserviceinfoadapter);
 
    tvtotalserviceno.settext("当前正在运行的服务共有:" + serviceinfolist.size());
  }
  // 获得系统正在运行的进程信息
  private void getrunningserviceinfo() {
 
    // 设置一个默认service的数量大小
    int defaultnum = 20;
    // 通过调用activitymanager的getrunningappservicees()方法获得系统里所有正在运行的进程
    list<activitymanager.runningserviceinfo> runservicelist = mactivitymanager
        .getrunningservices(defaultnum);
 
    system.out.println(runservicelist.size());
 
    // serviceinfo model类 用来保存所有进程信息
    serviceinfolist = new arraylist<runsericemodel>();
 
    for (activitymanager.runningserviceinfo runserviceinfo : runservicelist) {
 
      // 获得service所在的进程的信息
      int pid = runserviceinfo.pid; // service所在的进程id号
      int uid = runserviceinfo.uid; // 用户id 类似于linux的权限不同,id也就不同 比如 root等
      // 进程名,默认是包名或者由属性android:process指定
      string processname = runserviceinfo.process; 
 
      // 该service启动时的时间值
      long activesince = runserviceinfo.activesince;
 
      // 如果该service是通过bind方法方式连接,则clientcount代表了service连接客户端的数目
      int clientcount = runserviceinfo.clientcount;
 
      // 获得该service的组件信息 可能是pkgname/servicename
      componentname servicecmp = runserviceinfo.service;
      string servicename = servicecmp.getshortclassname(); // service 的类名
      string pkgname = servicecmp.getpackagename(); // 包名
 
      // 打印log
      log.i(tag, "所在进程id :" + pid + " 所在进程名:" + processname + " 所在进程uid:"
          + uid + "\n" + " service启动的时间值:" + activesince
          + " 客户端绑定数目:" + clientcount + "\n" + "该service的组件信息:"
          + servicename + " and " + pkgname);
 
      // 这儿我们通过service的组件信息,利用packagemanager获取该service所在应用程序的包名 ,图标等
      packagemanager mpackagemanager = this.getpackagemanager(); // 获取packagermanager对象;
 
      try {
        // 获取该pkgname的信息
        applicationinfo appinfo = mpackagemanager.getapplicationinfo(
            pkgname, 0);
 
        runsericemodel runservice = new runsericemodel();
        runservice.setappicon(appinfo.loadicon(mpackagemanager));
        runservice.setapplabel(appinfo.loadlabel(mpackagemanager) + "");
        runservice.setservicename(servicename);
        runservice.setpkgname(pkgname);
        // 设置该service的组件信息
        intent intent = new intent();
        intent.setcomponent(servicecmp);
        runservice.setintent(intent);
 
        runservice.setpid(pid);
        runservice.setprocessname(processname);
 
        // 添加至集合中
        serviceinfolist.add(runservice);
 
      } catch (namenotfoundexception e) {
        // todo auto-generated catch block
        system.out.println("--------------------- error -------------");
        e.printstacktrace();
      }
 
    }
  }
 
  // 触摸可停止
  @override
  public void onitemclick(adapterview<?> arg0, view arg1, int position,
      long arg3) {
    // todo auto-generated method stub
    final intent stopserviceintent = serviceinfolist.get(position)
        .getintent();
 
    new alertdialog.builder(browserunningserviceactivity.this).settitle(
        "是否停止服务").setmessage(
        "服务只有在重新启动后,才可以继续运行。但这可能会给电子市场应用程序带来意想不到的结果。")
        .setpositivebutton("停止", new dialoginterface.onclicklistener() {
 
          @override
          public void onclick(dialoginterface dialog, int which) {
            // todo auto-generated method stub
            // 停止该service
            //由于权限不够的问题,为了避免应用程序出现异常,捕获该securityexception ,并弹出对话框
            try {
              stopservice(stopserviceintent);
            } catch (securityexception sex) {
              //发生异常 说明权限不够 
              system.out.println(" deny the permission");
              new alertdialog.builder(browserunningserviceactivity.this).settitle(
              "权限不够").setmessage("对不起,您的权限不够,无法停止该service").create().show();
            }
            // 刷新界面
            // 获得正在运行的service信息
            getrunningserviceinfo();
            // 对集合排序
            collections.sort(serviceinfolist, new comparatorservicelable());
            // 为listview构建适配器对象
            browserunningserviceadapter mserviceinfoadapter = new browserunningserviceadapter(
                browserunningserviceactivity.this,
                serviceinfolist);
            listviewservice.setadapter(mserviceinfoadapter);
            tvtotalserviceno.settext("当前正在运行的服务共有:"
                + serviceinfolist.size());
          }
 
        }).setnegativebutton("取消",
            new dialoginterface.onclicklistener() {
 
              @override
              public void onclick(dialoginterface dialog,
                  int which) {
                // todo auto-generated method stub
                dialog.dismiss(); // 取消对话框
              }
            }).create().show();
  }
 
  // 自定义排序 根据applabel排序
  private class comparatorservicelable implements comparator<runsericemodel> {
 
    @override
    public int compare(runsericemodel object1, runsericemodel object2) {
      // todo auto-generated method stub
      return object1.getapplabel().compareto(object2.getapplabel());
    }
 
  }
 
}

延伸 · 阅读

精彩推荐