获取app运行次数运行时间等信息

本文详细介绍了如何在Eclipse环境下通过复制framework的class.jar文件加入工程,直接引用PkgUsageStats类,并通过反射调用其方法获取应用使用统计数据。重点讨论了权限需求,并提供了直接引用代码示例。同时,文章提到了数据获取的局限性和后续补充的可能性。

主要通过PkgUsageStats这个类来获取相关信息,在eclipse下编译,可通过复制framework的class.jar加入到工程,从而直接引用这个类,在源码下也能直接引用;也可以在eclipse单纯的sdk下使用反射来调用。注意权限!

PkgUsageStats.java的路径:framework/base/core/java/com/android/internal/os/PkgUsageStats.java

// use reflect
	// have to root and push into system/app
	private void getPkgUsageStats()
    {
		try {
			Class<?> cServiceManager = Class
					.forName("android.os.ServiceManager");
			Method mGetService = cServiceManager.getMethod("getService",
					java.lang.String.class);
			Object oRemoteService = mGetService.invoke(null, "usagestats");

			// IUsageStats oIUsageStats =
			// IUsageStats.Stub.asInterface(oRemoteService)
			Class<?> cStub = Class
					.forName("com.android.internal.app.IUsageStats$Stub");
			Method mUsageStatsService = cStub.getMethod("asInterface",
					android.os.IBinder.class);
			Object oIUsageStats = mUsageStatsService.invoke(null,
					oRemoteService);

			// PkgUsageStats[] oPkgUsageStatsArray =
			// mUsageStatsService.getAllPkgUsageStats();
			Class<?> cIUsageStatus = Class
					.forName("com.android.internal.app.IUsageStats");
			Method mGetAllPkgUsageStats = cIUsageStatus.getMethod(
					"getAllPkgUsageStats", (Class[]) null);
			Object[] oPkgUsageStatsArray = (Object[]) mGetAllPkgUsageStats
					.invoke(oIUsageStats, (Object[]) null);
			System.out.println(oPkgUsageStatsArray);

			Class<?> cPkgUsageStats = Class
					.forName("com.android.internal.os.PkgUsageStats");

			StringBuffer sb = new StringBuffer();
			sb.append("nerver used : ");
			for (Object pkgUsageStats : oPkgUsageStatsArray) {
				// get pkgUsageStats.packageName, pkgUsageStats.launchCount,
				// pkgUsageStats.usageTime
				String packageName = (String) cPkgUsageStats.getDeclaredField(
						"packageName").get(pkgUsageStats);
				int launchCount = cPkgUsageStats
						.getDeclaredField("launchCount").getInt(pkgUsageStats);
				long usageTime = cPkgUsageStats.getDeclaredField("usageTime")
						.getLong(pkgUsageStats);
				if(launchCount > 0)
					Log.v("getPkgUsageStats",packageName + "  count: " + launchCount + "  time:  "
						+ usageTime);
				else{
					sb.append(packageName+" ");
				}
			}
			Log.v("getPkgUsageStats",sb.toString());
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

直接引用的代码:

private void getPkgUsageStats2()
    {
		IUsageStats statsService = (IUsageStats) IUsageStats.Stub.
				asInterface(ServiceManager.getService("usagestats"));
		
		PkgUsageStats[] pkgStats = null;
		try {
			pkgStats = statsService.getAllPkgUsageStats();
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		if(pkgStats != null)
		{
			StringBuffer sb = new StringBuffer();
			sb.append("nerver used : ");
			for(PkgUsageStats usageStats : pkgStats)
			{
				String packageName = usageStats.packageName;
				int launchCount = usageStats.launchCount;
				long usageTime = usageStats.usageTime;
				if(launchCount > 0)
					Log.v("getPkgUsageStats",packageName + "  count: " + launchCount + "  time:  "
						+ usageTime);
				else{
					sb.append(packageName+" ");
				}
			}


			Log.v("getPkgUsageStats",sb.toString());
		}
    }
需要system权限,可以push进去,或者使用和手机的framework一样的签名。

另外,得到的数据感觉不是很多,但是开机后没有刷新掉,留待以后补充。

<think>好的,我现在需要帮助用户在MATLAB AppDesigner中使用EditField控件实时显示程序运行时间。首先,我得理解用户的需求。用户想要在程序运行时,EditField能够动态更新显示已经过去的时间,而不是等到程序结束后才显示总时间。这涉及到实时更新UI组件的问题。 根据之前的引用内容,特别是引用[3]中的例子,用户通过循环和drawnow函数实现了进度条的实时更新。类似的方法可能适用于时间显示。不过,时间的计算和更新方式可能有所不同,因为时间需要持续累加,而不是像进度条那样基于循环的迭代次数。 首先,我需要确定如何获取程序的运行时间。在MATLAB中,可以使用tic和toc函数来测量时间。但是,由于AppDesigner的回调函数通常是同步执行的,如果在回调函数中使用循环,界面可能会冻结,无法实时更新。因此,可能需要使用异步处理,比如使用定时器(timer)对象,或者在循环中插入drawnow命令来强制更新界面。 引用[3]的例子中,在for循环内部调用了drawnow来实时更新EditField的值。同样的方法可以应用到这里。用户可以在开始执行耗时操作之前记录开始时间,然后在循环或处理过程中不断计算已用时间,并更新到EditField中。 另外,需要注意MATLAB AppDesigner中的控件属性赋值规则。例如,引用[5]提到,EditField的Value属性需要字符类型,所以需要将数值转换为字符串。因此,在更新EditField时,必须将时间数值转换为字符串格式。 可能的实现步骤: 1. 在App Designer中添加一个EditField控件和一个按钮控件。 2. 在按钮的回调函数中,使用tic记录开始时间。 3. 启动一个循环或执行耗时任务,期间定期计算已用时间(toc),并将其转换为字符串更新到EditField。 4. 在每次更新后调用drawnow,确保界面及时刷新。 需要注意的是,如果任务本身是长时间运行的循环,直接在其中更新EditField并调用drawnow可能会导致界面响应缓慢,但这是必要的步骤。或者,考虑将耗时任务放在一个单独的定时器中,以避免阻塞主线程。 验证过程中,还需要确保时间显示的格式正确,比如转换为分钟、秒,或者保持毫秒精度,根据用户需求调整。例如,使用sprintf('%0.2f 秒', elapsedTime)来格式化时间显示。 可能的问题包括:界面卡顿、时间更新不及时、数据类型转换错误等。需要参考引用中的例子,特别是正确转换数值到字符串,并合理使用drawnow函数。 总结解决方案:在回调函数中使用tic开始计时,在循环或处理过程中不断调用toc获取已用时间,转换为字符串后赋值给EditField.Value,并调用drawnow实时更新。</think>### 分步实现方法 #### 步骤1:添加控件 1. 在App Designer界面中拖放一个 **EditField(数值或文本类型)** 和一个 **Button** 控件。 2. 设置EditField的`Tag`属性为`TimeDisplayField`(便于代码中引用)。 #### 步骤2:编写回调函数 在按钮的回调函数中添加以下代码: ```matlab function StartButtonPushed(app, event) % 记录开始时间 tStart = tic; % 初始化EditField显示 app.TimeDisplayField.Value = '0.00 秒'; % 模拟耗时操作(例如:循环或计算) for i = 1:100 % 执行实际任务... pause(0.1); % 模拟耗时步骤 % 计算已用时间 elapsedTime = toc(tStart); % 更新EditField(转换为字符串) app.TimeDisplayField.Value = sprintf('%.2f 秒', elapsedTime); % 强制刷新界面 drawnow; end end ``` #### 步骤3:关键细节说明 1. **时间格式转换**:使用`sprintf`将数值时间格式化为字符串(如`%.2f 秒`保留两位小数)[^5]。 2. **实时刷新**:在循环内调用`drawnow`保证界面实时更新[^3]。 3. **耗时操作模拟**:若实际任务不含循环,需改用定时器(`timer`)实现异步更新(见高级优化部分)。 #### 效果演示 程序运行时,EditField会动态显示从点击按钮开始累计的时间,精度为0.01秒。 --- ### 高级优化(异步更新) 若任务本身无法拆分为循环(如单次长耗时计算),需使用`timer`对象实现非阻塞更新: ```matlab function StartButtonPushed(app, event) % 创建定时器 t = timer('ExecutionMode', 'fixedRate', 'Period', 0.1); t.StartDelay = 0; t.TimerFcn = @(~,~) updateTime(app, tic); % 传递开始时间 % 启动定时器和任务 start(t); % 执行实际任务(此处用pause模拟) pause(5); stop(t); delete(t); end function updateTime(app, tStart) elapsedTime = toc(tStart); app.TimeDisplayField.Value = sprintf('%.2f 秒', elapsedTime); end ``` --- ### 常见问题解决 1. **界面卡顿**:确保在耗时循环中频繁调用`drawnow`。 2. **时间精度不足**:减小定时器的`Period`值(如0.01秒),但会增加计算负载。 3. **数据类型错误**:使用`string()`或`sprintf`确保赋值内容为字符串[^5]。 ---
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值