Android 开发获取程序启动次数
记录一些自己百度的东西 希望能够帮助你
获取Android系统中全部正在运行的程序
1、首先在Android中获取系统正在运行的进程方法是getRunningAppProcesses()。我们首先通过ActivityManager manager= (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);来获取系统的全局状态,然后通过调用getRunningAppProcesses()方法就可以获得系统正在运行的进程, 代码如下:
ActivityManager manager = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE); List2、 启动程序时
log日志会打印
“startActivitySafely:intent:Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER]”
这些内容,在后面是包名,你可以根据这些统计。
3、 应该是读取logcat,然后过滤所有程序启动都会带的ActivityManager,统计同一程序出现的次数。这个程序申请了android.permission.READ_LOGS 权限。通过market://search?q= 查询的相关应用信息
4、
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;/*** 程序运行需要在清单文件中添加*/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 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 list = servMng.getRunningAppProcesses(); |
03 | if (list != null ){ |
04 | for ( int i= 0 ;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 | } |
5、 http://www.cnblogs.com/leepood/archive/2011/02/26/1965716.html
android监控程序开启与关闭的代码
昨天把思路写下来了,今天上代码:package org.leepood.monitordemo;
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 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
最后一个关于权限问题 在源码中编译后 能够实现 但是涉及到源码签名 机子适配问题 不能在线升级 签名不好管理 不懂怎么处理 往看到的能给小弟留条信息 网上搜了一大堆 好多发帖 问的没没结贴 问题解决了 却没给我们小辈一些思路
最后实现 我是用sqlite3去记录的 获取栈顶包名 判断 记录 写入
更多相关文章
- Android 本地代码中的LIKELY和UNLIKELY宏
- Android高效加载大图、多图解决方案,有效避免程序内存溢出现象
- (4.1.12)Android高效加载大图、多图解决方案,有效避免程序OOM
- Cocos2dx android 部分代码的理解
- 【Android】内嵌html页面与native代码简单交互
- android点滴(8) -- android应用程序的生命周期
- Unity3D导出为android程序invokation failed