Intereting Posts

Приложение для мониторинга других приложений на Android

Проблема : я должен создать Service которая работает непрерывно. Эта служба следит за 5 приложениями, на вашем телефоне установлено 5 игр для Android. Эта служба должна получить информацию о: 1. Сколько раз игра открывается и запускается? 2. Сколько времени играла каждая игра.

Например: Say Если у меня эта служба установлена ​​в моем приложении. И я отпустил его на месяц. Мне нужна информация такого рода на экране приложения:

Игра Количество запусков игры Продолжительность игры

Игра 1 20 раз в течение 15 часов

Игра 2 16 раз в общей сложности 25 часов

..

..

Игра 5 10 раз в течение 12 часов

Возможный подход : когда приложение загружается, оно поступает в память. Отмечая время системных часов при запуске приложения. И когда приложение заканчивается или помещается в фоновом режиме, отмечая время снова.

Скажите, если приложение будет доставлено в память в 21:00 и выйдет на второй план в 9:30 вечера, что даст нам игровое время в 30 минут. В следующий раз, когда приложение воспроизводится, продолжительность будет добавлена ​​к 30 из предыдущего воспроизведения, сохраненного в какой-то переменной и так далее. Каждый раз, когда приложение вводится в память, счетчик его воспроизведения должен увеличиваться на единицу. Если мы даем нам количество раз, когда приложение воспроизводится.

Кодирование: я понятия не имею об Service в Android, поскольку я никогда на них не работал. Любые учебники, связанные с моей проблемой, будут очень полезны. Во-вторых, если есть другой способ, которым это можно было бы сделать. Я тоже хотел бы знать это. Я мог бы действительно использовать фрагмент кода для запуска этого проекта.

Solutions Collecting From Web of "Приложение для мониторинга других приложений на Android"

Как вы написали, задача состоит в том, чтобы отслеживать 3-сторонние сторонние приложения, нет другого решения, кроме периодически просматриваемого списка процессов и обнаружения процесса переднего плана . Для этого вам нужна услуга. К сожалению, Android не предоставляет таких средств, как широковещательные события для изменения процесса переднего плана.

На самом деле задача требует большого количества кода, по крайней мере, намного больше обычного ответа. Я размещаю его часть здесь, но вы должны учитывать многие нюансы, оставленные за кулисами, такие как синхронизация и постоянная информация между запусками. Это всего лишь скелет.

Во-первых, разрешите код для объекта приложения, что является хорошим местом для регистрации всех материалов, связанных с экземплярами.

MonitorApp

 public class MonitorApp extends Application { // actual store of statistics private final ArrayList<HashMap<String,Object>> processList = new ArrayList<HashMap<String,Object>>(); // fast-access index by package name (used for lookup) private ArrayList<String> packages = new ArrayList<String>(); public ArrayList<HashMap<String,Object>> getProcessList() { return processList; } public ArrayList<String> getPackages() { return packages; } // TODO: you need to save and load the instance data // TODO: you need to address synchronization issues } 

Затем дайте черновик действий.

MonitorActivity

 import static ProcessList.COLUMN_PROCESS_NAME; import static ProcessList.COLUMN_PROCESS_PROP; import static ProcessList.COLUMN_PROCESS_COUNT; import static ProcessList.COLUMN_PROCESS_TIME; public class MonitorActivity extends Activity implements MonitorService.ServiceCallback { private ArrayList<HashMap<String,Object>> processList; private MonitorService backgroundService; private MyCustomAdapter adapter = null; private ListView listView = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // TODO: provide your layout listView = (ListView)findViewById(R.id.id_process_listview); createAdapter(); this.bindService( new Intent(this, MonitorService.class), serviceConnection, Context.BIND_AUTO_CREATE); } private void createAdapter() { processList = ((MonitorApp)getApplication()).getProcessList(); adapter = new MyCustomAdapter(this, processList, R.layout.complex_list_item, new String[] { COLUMN_PROCESS_NAME, COLUMN_PROCESS_PROP, // TODO: you may calculate and pre-fill this field // from COLUMN_PROCESS_COUNT and COLUMN_PROCESS_TIME // so eliminating the need to use the custom adapter }, new int[] { android.R.id.text1, android.R.id.text2 }); listView.setAdapter(adapter); } // callback method invoked by the service when foreground process changed @Override public void sendResults(int resultCode, Bundle b) { adapter.notifyDataSetChanged(); } private class MyCustomAdapter extends SimpleAdapter { MyCustomAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to) { super(context, data, resource, from, to); } @Override public View getView (int position, View convertView, ViewGroup parent) { View result = super.getView(position, convertView, parent); // TODO: customize process statistics display int count = (Integer)(processList.get(position).get(COLUMN_PROCESS_COUNT)); int seconds = (Integer)(processList.get(position).get(COLUMN_PROCESS_TIME)); return result; } } private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { LocalBinder binder = (LocalBinder)service; backgroundService = binder.getService(); backgroundService.setCallback(MonitorActivity.this); backgroundService.start(); } @Override public void onServiceDisconnected(ComponentName className) { backgroundService = null; } }; @Override public void onResume() { super.onResume(); if(backgroundService != null) { backgroundService.setCallback(this); } } @Override public void onPause() { super.onPause(); if(backgroundService != null) { backgroundService.setCallback(null); } } } 

Эта деятельность запускает службу рабочего стола, которая фактически контролирует процессы. Вы могли бы перенести регистрацию службы из этой операции в экземпляр приложения. Сама услуга выглядит примерно так:

MonitorService

 public class MonitorService extends Service { private boolean initialized = false; private final IBinder mBinder = new LocalBinder(); private ServiceCallback callback = null; private Timer timer = null; private final Handler mHandler = new Handler(); private String foreground = null; private ArrayList<HashMap<String,Object>> processList; private ArrayList<String> packages; private Date split = null; public static int SERVICE_PERIOD = 5000; // TODO: customize (this is for scan every 5 seconds) private final ProcessList pl = new ProcessList(this) { @Override protected boolean isFilteredByName(String pack) { // TODO: filter processes by names, return true to skip the process // always return false (by default) to monitor all processes return false; } }; public interface ServiceCallback { void sendResults(int resultCode, Bundle b); } public class LocalBinder extends Binder { MonitorService getService() { // Return this instance of the service so clients can call public methods return MonitorService.this; } } @Override public void onCreate() { super.onCreate(); initialized = true; processList = ((MonitorApp)getApplication()).getProcessList(); packages = ((MonitorApp)getApplication()).getPackages(); } @Override public IBinder onBind(Intent intent) { if(initialized) { return mBinder; } return null; } public void setCallback(ServiceCallback callback) { this.callback = callback; } private boolean addToStatistics(String target) { boolean changed = false; Date now = new Date(); if(!TextUtils.isEmpty(target)) { if(!target.equals(foreground)) { int i; if(foreground != null && split != null) { // TODO: calculate time difference from current moment // to the moment when previous foreground process was activated i = packages.indexOf(foreground); long delta = (now.getTime() - split.getTime()) / 1000; Long time = (Long)processList.get(i).get(COLUMN_PROCESS_TIME); if(time != null) { // TODO: add the delta to statistics of 'foreground' time += delta; } else { time = new Long(delta); } processList.get(i).put(COLUMN_PROCESS_TIME, time); } // update count of process activation for new 'target' i = packages.indexOf(target); Integer count = (Integer)processList.get(i).get(COLUMN_PROCESS_COUNT); if(count != null) count++; else { count = new Integer(1); } processList.get(i).put(COLUMN_PROCESS_COUNT, count); foreground = target; split = now; changed = true; } } return changed; } public void start() { if(timer == null) { timer = new Timer(); timer.schedule(new MonitoringTimerTask(), 500, SERVICE_PERIOD); } // TODO: startForeground(srvcid, createNotification(null)); } public void stop() { timer.cancel(); timer.purge(); timer = null; } private class MonitoringTimerTask extends TimerTask { @Override public void run() { fillProcessList(); ActivityManager activityManager = (ActivityManager)MonitorService.this.getSystemService(ACTIVITY_SERVICE); List<RunningTaskInfo> taskInfo = activityManager.getRunningTasks(1); String current = taskInfo.get(0).topActivity.getPackageName(); // check if current process changed if(addToStatistics(current) && callback != null) { final Bundle b = new Bundle(); // TODO: pass necessary info to UI via bundle mHandler.post(new Runnable() { public void run() { callback.sendResults(1, b); } }); } } } private void fillProcessList() { pl.fillProcessList(processList, packages); } } на public class MonitorService extends Service { private boolean initialized = false; private final IBinder mBinder = new LocalBinder(); private ServiceCallback callback = null; private Timer timer = null; private final Handler mHandler = new Handler(); private String foreground = null; private ArrayList<HashMap<String,Object>> processList; private ArrayList<String> packages; private Date split = null; public static int SERVICE_PERIOD = 5000; // TODO: customize (this is for scan every 5 seconds) private final ProcessList pl = new ProcessList(this) { @Override protected boolean isFilteredByName(String pack) { // TODO: filter processes by names, return true to skip the process // always return false (by default) to monitor all processes return false; } }; public interface ServiceCallback { void sendResults(int resultCode, Bundle b); } public class LocalBinder extends Binder { MonitorService getService() { // Return this instance of the service so clients can call public methods return MonitorService.this; } } @Override public void onCreate() { super.onCreate(); initialized = true; processList = ((MonitorApp)getApplication()).getProcessList(); packages = ((MonitorApp)getApplication()).getPackages(); } @Override public IBinder onBind(Intent intent) { if(initialized) { return mBinder; } return null; } public void setCallback(ServiceCallback callback) { this.callback = callback; } private boolean addToStatistics(String target) { boolean changed = false; Date now = new Date(); if(!TextUtils.isEmpty(target)) { if(!target.equals(foreground)) { int i; if(foreground != null && split != null) { // TODO: calculate time difference from current moment // to the moment when previous foreground process was activated i = packages.indexOf(foreground); long delta = (now.getTime() - split.getTime()) / 1000; Long time = (Long)processList.get(i).get(COLUMN_PROCESS_TIME); if(time != null) { // TODO: add the delta to statistics of 'foreground' time += delta; } else { time = new Long(delta); } processList.get(i).put(COLUMN_PROCESS_TIME, time); } // update count of process activation for new 'target' i = packages.indexOf(target); Integer count = (Integer)processList.get(i).get(COLUMN_PROCESS_COUNT); if(count != null) count++; else { count = new Integer(1); } processList.get(i).put(COLUMN_PROCESS_COUNT, count); foreground = target; split = now; changed = true; } } return changed; } public void start() { if(timer == null) { timer = new Timer(); timer.schedule(new MonitoringTimerTask(), 500, SERVICE_PERIOD); } // TODO: startForeground(srvcid, createNotification(null)); } public void stop() { timer.cancel(); timer.purge(); timer = null; } private class MonitoringTimerTask extends TimerTask { @Override public void run() { fillProcessList(); ActivityManager activityManager = (ActivityManager)MonitorService.this.getSystemService(ACTIVITY_SERVICE); List<RunningTaskInfo> taskInfo = activityManager.getRunningTasks(1); String current = taskInfo.get(0).topActivity.getPackageName(); // check if current process changed if(addToStatistics(current) && callback != null) { final Bundle b = new Bundle(); // TODO: pass necessary info to UI via bundle mHandler.post(new Runnable() { public void run() { callback.sendResults(1, b); } }); } } } private void fillProcessList() { pl.fillProcessList(processList, packages); } } 

Служба использует вспомогательный класс для составления списков процессов.

PROCESSLIST

 public abstract class ProcessList { // process package name public static final String COLUMN_PROCESS_NAME = "process"; // TODO: arbitrary property (can be user-fiendly name) public static final String COLUMN_PROCESS_PROP = "property"; // number of times a process has been activated public static final String COLUMN_PROCESS_COUNT = "count"; // number of seconds a process was in foreground public static final String COLUMN_PROCESS_TIME = "time"; private ContextWrapper context; ProcessList(ContextWrapper context) { this.context = context; } protected abstract boolean isFilteredByName(String pack); public void fillProcessList(ArrayList<HashMap<String,Object>> processList, ArrayList<String> packages) { ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE); List<RunningAppProcessInfo> procInfo = activityManager.getRunningAppProcesses(); HashMap<String, Object> hm; final PackageManager pm = context.getApplicationContext().getPackageManager(); for(int i = 0; i < procInfo.size(); i++) { String process = procInfo.get(i).processName; String packageList = Arrays.toString(procInfo.get(i).pkgList); if(!packageList.contains(process)) { process = procInfo.get(i).pkgList[0]; } if(!packages.contains(process) && !isFilteredByName(process)) { ApplicationInfo ai; String applicationName = ""; for(int k = 0; k < procInfo.get(i).pkgList.length; k++) { String thisPackage = procInfo.get(i).pkgList[k]; try { ai = pm.getApplicationInfo(thisPackage, 0); } catch(final NameNotFoundException e) { ai = null; } if(k > 0) applicationName += " / "; applicationName += (String)(ai != null ? pm.getApplicationLabel(ai) : "(unknown)"); } packages.add(process); hm = new HashMap<String, Object>(); hm.put(COLUMN_PROCESS_NAME, process); hm.put(COLUMN_PROCESS_PROP, applicationName); processList.add(hm); } } // optional sorting Comparator<HashMap<String, Object>> comparator = new Comparator<HashMap<String, Object>>() { public int compare(HashMap<String, Object> object1, HashMap<String, Object> object2) { return ((String)object1.get(COLUMN_PROCESS_NAME)).compareToIgnoreCase((String)object2.get(COLUMN_PROCESS_NAME)); } }; Collections.sort(processList, comparator); packages.clear(); for(HashMap<String, Object> e : processList) { packages.add((String)e.get(COLUMN_PROCESS_NAME)); } } } 

Наконец, манифест.

AndroidManifest.xml

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.yourpackage" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="18" /> <uses-permission android:name="android.permission.GET_TASKS" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".MonitorActivity" android:label="@string/app_name" android:configChanges="orientation|keyboardHidden" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".MonitorService" /> </application> </manifest> 

Как вы можете видеть, это уже много кода. Он частично извлечен из рабочего приложения, но я сделал быстрые изменения для ваших нужд, поэтому могут быть опечатки, все импорт пропущен и т. Д. Тем не менее, я надеюсь, что это немного поможет.

ДОБАВЛЕНИЕ: Lollipop +

Опасайтесь: последние версии Android нарушили вышеупомянутый подход. Вот что говорится в официальной документации о методе getRunningTasks и других:

Что касается LOLLIPOP, этот метод больше не доступен для сторонних приложений: введение рецентов, ориентированных на документ, означает, что он может передавать информацию об абоненте вызывающей стороне. Для обратной совместимости он по-прежнему будет восстанавливать небольшое количество своих данных: по крайней мере, собственные задачи вызывающего абонента и, возможно, некоторые другие задачи, такие как дома, которые, как известно, не чувствительны.

Я думаю, что это перебор, и это можно сделать гораздо более избирательным и удобным способом. Не говоря уже о том, что это кажется слишком театральным, учитывая множество встроенных функций от Google с проблемами конфиденциальности. Во всяком случае, мы ничего не можем с этим поделать.

Единственным обходным решением является внедрение службы доступности Android (подробнее здесь и здесь ) и перехват всех действий с приложениями, получающими и теряющими фокус оттуда. Пользователь должен включить службу вручную! Ваше приложение должно каким-то образом направить пользователя на это.

Мои мысли,

  1. Разработайте приложение, которое делает некоторые из их данных общедоступными для другого процесса для доступа к ним.

    Google «Как использовать контент-провайдеры ».

    Каждый из ваших приложений должен будет вести учет всех действий, которые они выполняли. Эти данные будут общедоступными для доступа.

  2. Тогда вам не нужно запускать службу для этого. Всякий раз, когда ваше приложение мониторинга открывается. Просто нужно извлечь эти данные из всех приложений, которые вы хотите, и отобразить их соответственно.

  3. Для случая, когда вы хотите периодически отправлять эти данные на сервер в фоновом режиме. Тогда вам нужна услуга . Но все равно вам не нужно запускать его навсегда . Сделайте что-нибудь подобное.

    I) Из данных извлечения сервиса и загрузки на сервер.

    Ii) Остановите службу и заплатите будильник через некоторое время T1, чтобы снова запустить свой собственный сервис, чтобы снова выполнить шаг 1.

    Iii) T1 зависит от требования. Как обновить данные на сервере.

Я даже могу сказать вам указатель на фрагменты кода, если вы хотите, чтобы реализовать то, что я сказал выше. Но я предлагаю вам найти это в Google и сделать это самостоятельно. Отправьте другой конкретный вопрос в StackOverflow, если у вас возникнут какие-либо трудности.

Надеюсь это поможет. 🙂

Редактировать:

В первую очередь. Его единственный, кто должен закодировать в конце. Возьмите указатель и помощь отсюда. Не ожидайте полного кода. Подробнее см. Ниже.

A)

Вам нужно сделать ваши приложения в качестве контент-провайдера. Проверьте ссылку ниже. И следуйте приведенным в нем примерам. Вы попадете в приложение, чьи данные будут доступны другим. Легко идти вперед.

http://developer.android.com/guide/topics/providers/content-providers.html

http://developer.android.com/guide/topics/providers/content-provider-creating.html

http://www.vogella.com/articles/AndroidSQLite/article.html

Все ваши приложения для игр должны сделать доступ к данным общедоступными. Теперь, как только вы закончите с этим.

Теперь вам просто нужно получить доступ ко всем данным в вашем приложении мониторинга и отобразить его.

B)

Как я сказал, если вы хотите сделать это через сервис. Вам не нужно запускать его навсегда. Просто запустите сервис за один раз, загрузите данные из поставщика контента и сделайте все, что хотите. Установите будильник, чтобы вызвать службу на более позднем этапе, чтобы выполнить ту же операцию.

Я предполагаю, что каждые 10 минут ваш сервис может получать данные от поставщика контента (ваше приложение для игр, которое вы хотите контролировать). Это будет выглядеть следующим образом.

 public class MonitoringService extends Service { private static final String ACTION_FETCH = "action_fetch"; private static final int REPEAT_DATALOAD_INTERVAL_MS = 10 * 60 * 1000; // 10 Min private static PendingIntent makeSelfPendingIntent(Context context) { PendingIntent intent = PendingIntent.getService( context, 0, makeSelfIntent(context), 0); return intent; } private static Intent makeSelfIntent(Context context) { Intent intent = new Intent(context, MonitoringService.class); intent.setAction(ACTION_FETCH); return intent; } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent != null && intent.getAction() != null) { String action = intent.getAction(); if (action.equals(ACTION_FETCH)) { loadDataFromContentProviderDoWhateverYouWantThen(); setAlarmToRedoLoad(); stopSelf(); } } return Super.onStartCommand(intent, flags, startId); } private void setAlarmToRedoLoad() { AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + REPEAT_DATALOAD_INTERVAL_MS, makeSelfPendingIntent(getApplicationContext())); } private void loadDataFromContentProviderDoWhateverYouWantThen(){ check this link how to load data from content provider. as your games app are content providers. It should be loaded easily. then do whatever you want display, upload anything http://developer.android.com/guide/topics/providers/content-provider-basics.html } // Call this method from onCreate of your monitoring app public static void start(Context context) { Intent intent = makeSelfIntent(context); context.startService(intent); } } 

C) убедитесь, что вы разрешили пользователю своего приложения мониторинга прекратить эту службу в любое время. Не забывайте отменять будильник в этом случае. Поэтому он не бежит в фоновом режиме навсегда.

D) Вы также можете настроить вещание на основе вещания. Всякий раз, когда ваше приложение для игр сохраняет данные, они должны транслировать это событие и позволять вашей службе вызываться после прослушивания этой трансляции. Загружает его тогда только.

E) Как Фил также заявил, что вы можете пойти и в Google Analytics.

Как вы хотите на самом деле сделать это сейчас зависит от вашего требования

Надеюсь это поможет. Попробуйте и дайте мне знать, чем больше проблем вы сталкиваетесь

Используйте этот пример кода для проверки работы браузера

 ActivityManager activityManager = (ActivityManager) this.getSystemService( ACTIVITY_SERVICE ); List<RunningAppProcessInfo> procInfos = actvityManager.getRunningAppProcesses(); for(int i = 0; i < procInfos.size(); i++){ if(procInfos.get(i).processName.equals("com.android.browser")) { Toast.makeText(getApplicationContext(), "Browser is running", Toast.LENGTH_LONG).show(); } } 

Чтобы создать службу, вам необходимо создать класс, который простирается от базового класса Service и реализовать функцию в бесконечном цикле, например while(true) в функции onStartCommand() . Не забудьте добавить свою службу в файл манифеста между тегами <service></service> , хороший учебник находится на http://www.vogella.com/articles/AndroidServices/article.html

Следующие решения основаны на предположении, что у вас есть все пять приложений, которые вы пытаетесь контролировать. Если это разумно, я дам вам другое решение.

Давайте разберем проблему сейчас.

  1. Информационная служба о запуске приложения или нет.
  2. Проектирование услуг
  3. Хранение данных

Вы должны использовать Intent для трансляции сообщений о вашем приложении или нет. Используйте активность onPause и onResume для трансляции сообщений.

Теперь вызовите эту функцию из onPause и onResume,

  public void broadcastMessage(String method_name){ Intent intent=new Intent("com.service.myservice"); Bundle bundle=new Bundle(); bundle.putString("app_name", this.getApplicationInfo().packageName); bundle.putLong("time", System.currentTimeMillis()); //just to keep track if it is on pause or in on resume bundle.putString("method", method_name); intent.putExtras(bundle); this.startService(intent); } 

И вы можете назвать это следующим образом

 public void onPause(){ super.onPause(); broadcastMessage(Thread.currentThread().getStackTrace()[1].getMethodName()); } 

Или

 public void onPause(){ super.onPause(); broadcastMessage("onPause"); } 

Итак, почему onPause и onResume, потому что геймер играет в игру только между этими вызовами функций.

Проектирование услуг

Используйте IntentService и прочитайте это, если хотите узнать почему.

 @Override protected void onHandleIntent(Intent intent) { // TODO Auto-generated method stub Bundle bundle=intent.getExtras(); String app_name=bundle.getString("app_name"); long time=bundle.getLong("time"); //then do whatever you wanna do with this data } 

хранения

ContentProvider – хороший вариант для хранения данных, а также очень мощный; Хорошо интегрируются и масштабируются на Android, но в этом случае кажется, что вы хотите хранить только очень простую информацию, и поэтому вы также можете выбрать что-то очень простое.

В приведенном ниже SharedPreferences используется SharedPreferences .

  protected void storeData(String app_name, long time) { if ((app_name==null)||(time<=0)) return; SharedPreferences sharedPreferences = PreferenceManager .getDefaultSharedPreferences(getApplicationContext()); Editor editor = sharedPreferences.edit(); //concatenating app name just to make key unique long start_time=sharedPreferences.getLong(app_name+"_start_time", -1); if (start_time==-1){ //start time is empty means this is my start time // and user just started the app editor.putLong(app_name+"_start_time", time); editor.putLong(app_name+"_counter", sharedPreferences.getLong(app_name+"_counter", 0)+1); }else{ //user is now closing the app. long time_played=time-start_time; long total_time=sharedPreferences.getLong(app_name+"_total_time", 0); total_time=total_time+time_played; //saving total time editor.putLong(app_name+"_total_time", time); //removing start time for next pass editor.remove(app_name+"_start_time"); } editor.commit(); } public long getTotalTimeUserSpent(String app_name){ SharedPreferences sharedPreferences = PreferenceManager .getDefaultSharedPreferences(getApplicationContext()); return sharedPreferences.getLong(app_name+"_total_time", 0); } public long numberOfTimeUserPlayed(String app_name){ SharedPreferences sharedPreferences = PreferenceManager .getDefaultSharedPreferences(getApplicationContext()); return sharedPreferences.getLong(app_name+"_counter", 0); } 

Просто вызовите этот метод из onHandleIntent .

Последний кусок головоломки будет распространением. Вы можете распространять это в отдельном приложении или части этих пяти приложений. Отдельные приложения – это самый простой способ. Но если вы решите использовать это как часть всех пяти этих приложений, прочитайте это обсуждение.

Чтобы получить текущее запущенное приложение, вы можете использовать:

 ActivityManager am = (ActivityManager) mContext.getSystemService(Activity.ACTIVITY_SERVICE); String packageName = am.getRunningTasks(1).get(0).topActivity.getPackageName(); 

Вы можете периодически проверять это из своего текущего сервиса. Вам также нужно будет указать требуемое разрешение в вашем манифесте: android.permission.GET_TASKS

Установка Covenant Eyes на Android-устройстве будет отслеживать весь интернет-трафик в предустановленном браузере телефона и сообщать о дополнительных приложениях, которые используются на устройстве.