Android 取得應用程式的啟動次數和執行時間等資訊
阿新 • • 發佈:2019-01-26
使用情景:最近有個需求是統計後臺應用執行時間,如果一個應用在後臺執行超過一定時間就Kill掉程序,達到省電的目的。此時就可以使用PkgUsageStats這個類來實現啦!
通過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的詳細使用資訊:
import com.android.internal.app.IUsageStats; import com.android.settings.R; import android.app.Activity; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; import com.android.internal.os.PkgUsageStats; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.ListView; import android.widget.Spinner; import android.widget.TextView; import android.widget.AdapterView.OnItemSelectedListener; /** * Activity to display package usage statistics. */ public class UsageStats extends Activity implements OnItemSelectedListener { private static final String TAG="UsageStatsActivity"; private static final boolean localLOGV = true; private Spinner mTypeSpinner; private ListView mListView; private IUsageStats mUsageStatsService; private LayoutInflater mInflater; private UsageStatsAdapter mAdapter; private PackageManager mPm; public static class AppNameComparator implements Comparator<PkgUsageStats> { Map<String, CharSequence> mAppLabelList; AppNameComparator(Map<String, CharSequence> appList) { mAppLabelList = appList; } public final int compare(PkgUsageStats a, PkgUsageStats b) { String alabel = mAppLabelList.get(a.packageName).toString(); String blabel = mAppLabelList.get(b.packageName).toString(); return alabel.compareTo(blabel); } } public static class LaunchCountComparator implements Comparator<PkgUsageStats> { public final int compare(PkgUsageStats a, PkgUsageStats b) { // return by descending order return b.launchCount - a.launchCount; } } public static class UsageTimeComparator implements Comparator<PkgUsageStats> { public final int compare(PkgUsageStats a, PkgUsageStats b) { long ret = a.usageTime-b.usageTime; if (ret == 0) { return 0; } if (ret < 0) { return 1; } return -1; } } // View Holder used when displaying views static class AppViewHolder { TextView pkgName; TextView launchCount; TextView usageTime; } class UsageStatsAdapter extends BaseAdapter { // Constants defining order for display order private static final int _DISPLAY_ORDER_USAGE_TIME = 0; private static final int _DISPLAY_ORDER_LAUNCH_COUNT = 1; private static final int _DISPLAY_ORDER_APP_NAME = 2; private int mDisplayOrder = _DISPLAY_ORDER_USAGE_TIME; private List<PkgUsageStats> mUsageStats; private LaunchCountComparator mLaunchCountComparator; private UsageTimeComparator mUsageTimeComparator; private AppNameComparator mAppLabelComparator; private HashMap<String, CharSequence> mAppLabelMap; UsageStatsAdapter() { mUsageStats = new ArrayList<PkgUsageStats>(); mAppLabelMap = new HashMap<String, CharSequence>(); PkgUsageStats[] stats; try { stats = mUsageStatsService.getAllPkgUsageStats(); } catch (RemoteException e) { Log.e(TAG, "Failed initializing usage stats service"); return; } if (stats == null) { return; } for (PkgUsageStats ps : stats) { mUsageStats.add(ps); // load application labels for each application CharSequence label; try { ApplicationInfo appInfo = mPm.getApplicationInfo(ps.packageName, 0); label = appInfo.loadLabel(mPm); } catch (NameNotFoundException e) { label = ps.packageName; } mAppLabelMap.put(ps.packageName, label); } // Sort list mLaunchCountComparator = new LaunchCountComparator(); mUsageTimeComparator = new UsageTimeComparator(); mAppLabelComparator = new AppNameComparator(mAppLabelMap); sortList(); } public int getCount() { return mUsageStats.size(); } public Object getItem(int position) { return mUsageStats.get(position); } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { // A ViewHolder keeps references to children views to avoid unneccessary calls // to findViewById() on each row. AppViewHolder holder; // When convertView is not null, we can reuse it directly, there is no need // to reinflate it. We only inflate a new View when the convertView supplied // by ListView is null. if (convertView == null) { convertView = mInflater.inflate(R.layout.usage_stats_item, null); // Creates a ViewHolder and store references to the two children views // we want to bind data to. holder = new AppViewHolder(); holder.pkgName = (TextView) convertView.findViewById(R.id.package_name); holder.launchCount = (TextView) convertView.findViewById(R.id.launch_count); holder.usageTime = (TextView) convertView.findViewById(R.id.usage_time); convertView.setTag(holder); } else { // Get the ViewHolder back to get fast access to the TextView // and the ImageView. holder = (AppViewHolder) convertView.getTag(); } // Bind the data efficiently with the holder PkgUsageStats pkgStats = mUsageStats.get(position); if (pkgStats != null) { CharSequence label = mAppLabelMap.get(pkgStats.packageName); holder.pkgName.setText(label); holder.launchCount.setText(String.valueOf(pkgStats.launchCount)); holder.usageTime.setText(String.valueOf(pkgStats.usageTime)+" ms"); } else { Log.w(TAG, "No usage stats info for package:" + position); } return convertView; } void sortList(int sortOrder) { if (mDisplayOrder == sortOrder) { // do nothing return; } mDisplayOrder= sortOrder; sortList(); } private void sortList() { if (mDisplayOrder == _DISPLAY_ORDER_USAGE_TIME) { if (localLOGV) Log.i(TAG, "Sorting by usage time"); Collections.sort(mUsageStats, mUsageTimeComparator); } else if (mDisplayOrder == _DISPLAY_ORDER_LAUNCH_COUNT) { if (localLOGV) Log.i(TAG, "Sorting launch count"); Collections.sort(mUsageStats, mLaunchCountComparator); } else if (mDisplayOrder == _DISPLAY_ORDER_APP_NAME) { if (localLOGV) Log.i(TAG, "Sorting by application name"); Collections.sort(mUsageStats, mAppLabelComparator); } notifyDataSetChanged(); } } /** Called when the activity is first created. */ protected void onCreate(Bundle icicle) { super.onCreate(icicle); mUsageStatsService = IUsageStats.Stub.asInterface(ServiceManager.getService("usagestats")); if (mUsageStatsService == null) { Log.e(TAG, "Failed to retrieve usagestats service"); return; } mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); mPm = getPackageManager(); setContentView(R.layout.usage_stats); mTypeSpinner = (Spinner) findViewById(R.id.typeSpinner); mTypeSpinner.setOnItemSelectedListener(this); mListView = (ListView) findViewById(R.id.pkg_list); // Initialize the inflater mAdapter = new UsageStatsAdapter(); mListView.setAdapter(mAdapter); } public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { mAdapter.sortList(position); } public void onNothingSelected(AdapterView<?> parent) { // do nothing } }