原文:http://blog.csdn.net/xsl1990/article/details/21184435
记录一些自己百度的东西 希望能够帮助你
获取Android系统中全部正在运行的程序
1、
首先在Android中获取系统正在运行的进程方法是getRunningAppProcesses()。我们首先通过ActivityManager manager= (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);来获取系统的全局状态,然后通过调用getRunningAppProcesses()方法就可以获得系统正在运行的进程, 代码如下:
log日志会打印
“startActivitySafely:intent:Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER]”
这些内容,在后面是包名,你可以根据这些统计。
Android 编程下监视应用程序的启动
http://www.cnblogs.com/sunzn/archive/2013/02/13/2910906.html在进行程序锁开发的时候,我们会发现程序锁实现的核心难点是如何监视应用程序的启动,于是我们主要着手实现如何对应用程序的启动进行监测,这个功能的实现经历了三种方案的尝试,也符合我们实际开发中的思路,具体的实现过程如下:
- 尝试方案一
设想每个应用在启动的时候会发送一个广播,那么我们就能通过广播接收者来订阅这个广播从而达到监视应用程序启动的目的,于是我们在广播接收者的动作名称中去寻找这样的广播动作,但是很可惜系统并没有为我们提供这样一种广播。
- 尝试方案二
设想系统自身是否有一个服务对应用程序的启动做监视,如果这个服务里面的一个方法能够得到前台应用任务栈最顶端的 Activity,那么我们也能够达到监视应用程序启动的目的;一般情况下,系统的服务都是以 aidl 的形式出现的,这是因为系统底层的服务都封装在 Application Framework 层,而开发者的调用是在 Applications 层,这种调用属跨进程的调用,所以 Applications 层和 Application Framework 层的交互需要通过 aidl 来实现,于是我们就可以在系统源码中查找与之相关的 aidl 文件,但是同样系统也没有提供这样的一种服务。
- 尝试方案三
设想应用程序在启动过程中 LogCat 是否会对 Activity 的启动进行记录,于是我们尝试启动安卓手机上的系统应用计算器来观察 LogCat 的日志,通过对日志的观察我们发现 ActivityManager 可以检测到应用的 Activity 的启动,如下图:
有了上面的信息,我们就可以从 ActivityManager 入手来实现监视应用程序的启动,经过尝试 ActivityManager 的 API 可以通过如下代码来实现对应用程序启动的监视了。
package cn.sunzn.activitymonitor; import java.util.List; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; import android.content.ComponentName; import android.os.Bundle; import android.os.SystemClock; import android.util.Log; import android.view.Menu; /** * 程序运行需要在清单文件中添加 <uses-permission android:name="android.permission.GET_TASKS"/> */ public class MainActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /** 获取系统服务 ActivityManager */ ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); while (true) { /** 获取当前正在运行的任务栈列表, 越是靠近当前运行的任务栈会被排在第一位,之后的以此类推 */ List<RunningTaskInfo> runningTasks = manager.getRunningTasks(1); /** 获得当前最顶端的任务栈,即前台任务栈 */ RunningTaskInfo runningTaskInfo = runningTasks.get(0); /** 获取前台任务栈的最顶端 Activity */ ComponentName topActivity = runningTaskInfo.topActivity; /** 获取应用的包名 */ String packageName = topActivity.getPackageName(); /** 输出检测到的启动应用信息 */ Log.i("sunzn", packageName); /** 为了便于观察信息的输出,程序休眠2秒 */ SystemClock.sleep(2000); } } public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
实现以上的代码后,我们将该程序部署到模拟器进行测试,通过测试我们会发现被启动的应用程序的包名都会被输出到 LogCat 界面,这也就证明程序成功的检测到了应用程序的启动,所以程序锁的实现即可以此为基础将得到的包名与加锁应用数据库中的数据进行比对来实现应用程序启动时 是否进行密码验证的功能。最后的测试图如下,在下面的测试结果中我们可以发现程序成功的检测到了浏览器和计算器的启动。
List<ActivityManager.RunningAppProcessInfo> list = servMng.getRunningAppProcesses(); |
03 | if (list != null ){ |
04 | for ( int i= 0 ;i<list.size();++i){ |
05 | if ( "com.android.email" .matches(list.get(i).processName)){ |
06 | int pid = android.os.Process.getUidForName( "com.android.email" ); |
07 | android.os.Process.killProcess(pid); |
08 | } else { |
09 | mTextVIew.append(list.get(i).processName + "\n" ); |
10 | } |
11 | } |
12 | } |
android监控程序开启与关闭的代码
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.ActivityManager;
import android.app.Service;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
public class monitorApp extends Service {
public static final String ACTION = " org.leepood.monitordemo.APPS_CHANGED " ; // 自定义动作
private ActivityManager am = null ;
private HashMap < String,Integer > appsStored = null ; // 保存开启和关闭的程序进程名称列表
private final int STARTED_APP = 0 ; // 刚开启的程序标记为0
private final int CLOSED_APP = 1 ; // 刚关闭的程序标记为1
@Override
public IBinder onBind(Intent arg0) {
return null ;
}
@Override
public void onCreate() {
am = (ActivityManager) this .getSystemService(Context.ACTIVITY_SERVICE);
Log.i( " service-----> " , " start " );
}
@Override
public void onStart(Intent intent, int startId) {
Thread th_monitor = new Thread( new Runnable(){
@Override
public void run() {
while ( true )
{
appsStored = new HashMap < String,Integer > ();
/**
* 获取正在运行程序进程名称列表
*/
List < RunningAppProcessInfo > oldrunningapps = am.getRunningAppProcesses(); // 获取运行的程序
List < String > oldrunningappsprocessnameList = new ArrayList < String > (); // 保存所有正在运行程序的进程名称
for (RunningAppProcessInfo old:oldrunningapps)
{
oldrunningappsprocessnameList.add(old.processName);
Log.i( " old " , old.processName);
}
try {
Thread.sleep( 1000 ); // 休眠一段时间
} catch (InterruptedException e) {
e.printStackTrace();
}
/**
* 再次获取所有正在运行的程序名称列表
*/
List < RunningAppProcessInfo > newrunningapps = am.getRunningAppProcesses(); // 再次获取运行的程序
List < String > newrunningappsprocessnameList = new ArrayList < String > (); // 再次保存所有正在运行程序的进程名称
for (RunningAppProcessInfo newapp:newrunningapps)
{
newrunningappsprocessnameList.add(newapp.processName);
// Log.i("new", newapp.processName);
}
/**
* 开始比对
*/
for (String newapp:newrunningappsprocessnameList)
{
// 如果新获取的程序在原来获取的程序列表中则该程序没有变化,否则该程序为刚启动
if ( ! oldrunningappsprocessnameList.contains(newapp))
{
appsStored.put(newapp,STARTED_APP);
Log.i( " newstart " ,newapp);
}
}
for (String oldapp:oldrunningappsprocessnameList)
{
// 如果以前获取的程序在刚刚获取的程序列表中则该程序没有变化,否则该程序为刚关闭
if ( ! newrunningappsprocessnameList.contains(oldapp))
{
appsStored.put(oldapp,CLOSED_APP);
Log.i( " newclose " , oldapp);
}
}
// 发出广播
if (appsStored.size() != 0 )
{
Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putSerializable( " app_info " , appsStored);
intent.putExtra( " bundle " , bundle);
intent.setAction(ACTION);
monitorApp. this .sendBroadcast(intent);
Log.i( " sendbroadcast " , " true " );
appsStored = null ;
}
}
}
});
th_monitor.start();//启动监控线程
}
}
上面是代码的关键部位,利用线程来不断获取这一刻运行的进程与前一刻获取的简称比对,如果出现不同的则加以判断得出是新开启的还是刚关闭的.当然,有些程序即使你退出了还是会有进程在运行,所以是无法捕获的.我在用线程来获取运行的程序让其休眠了1秒中,个人觉得还是可以的。好了,这个服务可以通过开机的时候订阅开机广播来启动。要获取程序启动与关闭的信息,可以订阅我定义的这个。恩,附上源码。(本人系菜鸟欢迎各位指出其中的不足)源码下载
6、
通过这个方法可以你的task被转到后台了。如果你弄个定时器不停监控前台task,看是否有变化,应该可以 ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<RunningTaskInfo> taskInfo = am.getRunningTasks(1); if (!taskInfo.isEmpty()) { ComponentName topActivity = taskInfo.get(0).topActivity; if (!topActivity.getPackageName().equals(context.getPackageName())) { return true; } } return false; } |
- 通过com.android.internal.os.PkgUsageStats这个类可以得到一个应用程序的启动次数,运行时间等信息,功能很强大。但是google并没有将这个类作为API接口提供给开发者,如果在android源码下开发,可以通过以下代码来使用这个类:
- import com.android.internal.app.IUsageStats;
- import com.android.internal.os.PkgUsageStats;
- //比较两个应用程序的启动次数和运行时间
- public final int compare(ApplicationInfo a, ApplicationInfo b) {
- ComponentName aName = a.intent.getComponent();
- ComponentName bName = b.intent.getComponent();
- int result = 0;
- //get usagestats service
- IUsageStats mUsageStatsService = IUsageStats.Stub
- .asInterface(ServiceManager.getService("usagestats"));
- try {
- //get PkgUsageStats
- PkgUsageStats aStats = mUsageStatsService
- .getPkgUsageStats(aName);
- PkgUsageStats bStats = mUsageStatsService
- .getPkgUsageStats(bName);
- if(aStats!=null && bStats!=null) {
- if ((aStats.launchCount > bStats.launchCount)
- || ((aStats.launchCount == bStats.launchCount) && (aStats.usageTime > bStats.usageTime)))
- result = -1;
- else if ((aStats.launchCount < bStats.launchCount)
- || ((aStats.launchCount == bStats.launchCount) && (aStats.usageTime < bStats.usageTime)))
- result = 1;
- else {
- result = 0;
- }
- }else if(aStats!=null && bStats ==null) {
- result = -1;
- } else if(aStats==null && bStats !=null) {
- result = 1;
- }
- } catch (RemoteException e) {
- Log.i("TAG", "get package usage stats fail");
- }
- return result;
- }
- 那么如果想在sdk中使用这个 类要如果作呢--可以使用反射 的方法,代码如下:
- public final int compare(ApplicationInfo a, ApplicationInfo b) {
- ComponentName aName = a.intent.getComponent();
- ComponentName bName = b.intent.getComponent();
- int aLaunchCount,bLaunchCount;
- long aUseTime,bUseTime;
- int result = 0;
- try {
- //获得ServiceManager类
- Class<?> ServiceManager = Class
- .forName("android.os.ServiceManager");
- //获得ServiceManager的getService方法
- Method getService = ServiceManager.getMethod("getService", java.lang.String.class);
- //调用getService获取RemoteService
- Object oRemoteService = getService.invoke(null, "usagestats");
- //获得IUsageStats.Stub类
- Class<?> cStub = Class
- .forName("com.android.internal.app.IUsageStats$Stub");
- //获得asInterface方法
- Method asInterface = cStub.getMethod("asInterface", android.os.IBinder.class);
- //调用asInterface方法获取IUsageStats对象
- Object oIUsageStats = asInterface.invoke(null, oRemoteService);
- //获得getPkgUsageStats(ComponentName)方法
- Method getPkgUsageStats = oIUsageStats.getClass().getMethod("getPkgUsageStats", ComponentName.class);
- //调用getPkgUsageStats 获取PkgUsageStats对象
- Object aStats = getPkgUsageStats.invoke(oIUsageStats, aName);
- Object bStats = getPkgUsageStats.invoke(oIUsageStats, bName);
- //获得PkgUsageStats类
- Class<?> PkgUsageStats = Class.forName("com.android.internal.os.PkgUsageStats");
- aLaunchCount = PkgUsageStats.getDeclaredField("launchCount").getInt(aStats);
- bLaunchCount = PkgUsageStats.getDeclaredField("launchCount").getInt(bStats);
- aUseTime = PkgUsageStats.getDeclaredField("usageTime").getLong(aStats);
- bUseTime = PkgUsageStats.getDeclaredField("usageTime").getLong(bStats);
- if((aLaunchCount>bLaunchCount)||
- ((aLaunchCount == bLaunchCount)&&(aUseTime>bUseTime)))
- result = 1;
- else if((aLaunchCount<bLaunchCount)||((aLaunchCount ==
- bLaunchCount)&&(aUseTime<bUseTime)))
- result = -1;
- else {
- result = 0;
- }
- } catch (Exception e) {
- Log.e("###", e.toString(), e);
- }
- return result;
- }
- 如何看自己的android的详细使用信息:
- 我们使用Andoroid手机时想看看自己的手机的使用情况,那么我们又如何去操作呢?也是必需得像程序这样要自己写一个程序才能查看吧,如果用户不是编程的,那得怎么办,呵,其实我们查看自己的手机使用详情是没有那么复杂的,今天androidkaifa.com就会大家说一下如何查询自己的手机的使用情况,下面是具体的查看方法,
- 其实查看方法非常简单,直接进入Android的工程模式即可,操作步骤如下:(笔者的android手机系统是4.0)
- 1、首先进入Android手机操作系统的拨号界面,直接输入“*#*#4636#*#*”(不加引号)即可以快速进入Android操作系统的工程测试模式。
- 2、在“测试”模式菜单中有手机信息“Phone information”、电池信息“Battery information”、WI-FI信息“WI-FI information”、使用状态“Usage statistics”四个选项。
- 3、我们点击选择第二项“Battery information”进入电池信息,然后就可以看到手机电池的详细信息了,其中包括电量等级、电池状态、温度、电池材质、电压等等信息。
- 4: 我们相应点击其实的选择就可以看到其实的相应的使用详细信息