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

作者:qinjuning 时间:2023-01-19 21:05:42 

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中获得正在运行的程序和系统服务的方法

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



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中获得正在运行的程序和系统服务的方法

主工程逻辑如下:


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());
   }

}

}
标签:Android,正在运行
0
投稿

猜你喜欢

  • Java如何基于command调用openssl生成私钥证书

    2023-08-09 11:55:39
  • Android 文件数据存储实例详解

    2023-07-28 17:08:03
  • Spring事务管理方法步骤解析

    2021-12-15 20:09:04
  • java IO流将一个文件拆分为多个子文件代码示例

    2023-08-30 12:46:15
  • Android自定义控件实现简单滑动开关效果

    2022-09-07 16:46:01
  • spring Boot打包部署到远程服务器的tomcat中

    2023-01-14 21:45:28
  • C#中XmlTextWriter读写xml文件详细介绍

    2022-01-26 05:13:48
  • 如何使用HttpClient发送java对象到服务器

    2022-10-29 06:45:51
  • Flutter封装组动画混合动画AnimatedGroup示例详解

    2022-12-29 17:17:05
  • java针对电话号码正则匹配实例

    2023-07-15 05:49:32
  • 百度人脸识别之人脸识别FaceIdentify(签到考勤)

    2022-08-24 18:25:03
  • C#使用NPOI实现Excel导入导出功能

    2022-11-01 22:36:19
  • Mybatis-plus自动填充不生效或自动填充数据为null原因及解决方案

    2021-08-16 02:18:42
  • C#中Lambda表达式的用法

    2022-07-29 17:29:56
  • WPF使用DrawingContext实现绘制刻度条

    2023-06-19 08:35:17
  • java 在Jetty9中使用HttpSessionListener和Filter

    2021-10-01 14:44:00
  • C#使用DoddleReport快速生成报表

    2022-05-31 06:39:59
  • C# TextBox 扩展方法数据验证详细说明

    2022-05-07 14:21:36
  • Android实现短信验证功能的代码

    2022-08-28 19:54:15
  • Unity 实现鼠标滑过UI时触发动画的操作

    2021-05-31 19:24:18
  • asp之家 软件编程 m.aspxhome.com