package com.iwedia.service.system.application;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.util.Log;
import com.iwedia.comm.content.applications.AppItem;
import com.iwedia.comm.enums.AppListType;
import com.iwedia.comm.system.application.AppPermission;
import com.iwedia.service.IWEDIAService;
import com.iwedia.service.system.SystemControl;
/**
* This class manages applications, their details and settings, registers
* broadcast receivers and reacts on appropriate action intent.
*
* @author Stanislava Markovic
*/
@SuppressLint("NewApi")
public class ApplicationManager {
private final String LOG_TAG = "ApplicationManager";
private final String CONFIG_FILE_NAME = "application_config.txt";
private final String CONFIG_FILE_NAME_TARGET = "/data/data/com.iwedia.service/";
private PackageReceiver applicationReceiver;
private ShutdownReceiver shutdownReceiver;
private ArrayList<String> configFile;
private Context activity;
private static ApplicationManager instance;
private ArrayList<AppItem> allAppsList;
private ArrayList<Integer> allAppsIndexList;
private ArrayList<Integer> installAppsIndexList;
private ArrayList<Integer> contentAppsIndexList;
private int appTypeGlobal = AppListType.NONE;
private static String packageNameGlobal = "";
// force stop
private Object am;
private Class<?> ActivityManagerNative;
private Class<?> IActivityManager;
private Method getDefault;
private Method forceStopPackage;
// delete packages
private PackageObserverManager pom;
// app size info
private ApplicationInfo appInfo;
private List<AppPermission> appPermissions;
private AppSecurityPermissions appSecurityPermissions;
private ArrayList<ComponentName> prefActList;
private ArrayList<IntentFilter> intentList;
// process
private ArrayList<AppItem> runningServices;
/**
* ApplicationManager constructor. Initializes values and registers
* broadcast receivers.
*
* @param activity
*/
public ApplicationManager(Context activity) {
this.activity = activity;
instance = this;
applicationReceiver = new PackageReceiver();
shutdownReceiver = new ShutdownReceiver();
try {
pom = new PackageObserverManager(IWEDIAService.getContext());
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_PACKAGE_INSTALL);
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
intentFilter.addAction(Intent.ACTION_PACKAGE_FIRST_LAUNCH);
intentFilter.addDataScheme("package");
activity.registerReceiver(applicationReceiver, intentFilter);
IntentFilter intentFilterShutDown = new IntentFilter();
intentFilterShutDown.addAction(Intent.ACTION_SHUTDOWN);
activity.registerReceiver(shutdownReceiver, intentFilterShutDown);
copyFile();
readFile();
initApplications();
}
/**
* Gets the instance of the ApplicationManager class.
*
* @return instance of the ApplicationManager class.
*/
public static ApplicationManager getInstance() {
return instance;
}
/**
* Gets the instance of the ApplicationManager class.
*
* @param packageName
* - package name.
* @return instance of the ApplicationManager class.
*/
public static ApplicationManager getInstance(String packageName) {
packageNameGlobal = packageName;
return instance;
}
/**
* Sets application type.
*
* @param appType
* - application type.
*/
public void setAppType(int appType) {
appTypeGlobal = appType;
}
/**
* Gets application with the given index.
*
* @param index
* - application index.
* @return application with the given index.
*/
public AppItem getApplication(int index) {
int indexInAllAppsList = 0;
switch (appTypeGlobal) {
case AppListType.ALL:
indexInAllAppsList = allAppsIndexList.get(index);
break;
case AppListType.INSTALLED:
indexInAllAppsList = installAppsIndexList.get(index);
break;
case AppListType.CONTENT:
Log.e(LOG_TAG, "PackageReceiver "
+ "AppListType.CONTENT allAppsList.size() : "
+ allAppsList.size());
indexInAllAppsList = contentAppsIndexList.get(index);
break;
default:
break;
}
// if (appTypeGlobal == AppListType.RUNNING)
// return runningServices.get(index);
return allAppsList.get(indexInAllAppsList);
}
/**
* Gets size of application list with the given type.
*
* @param appType
* - application type - can be one of following: AppListType.ALL,
* AppListType.INSTALLED, AppListType.CONTENT
* @return size of application list.
*/
public int getSize(int appType) {
appTypeGlobal = appType;
int size = 0;
switch (appType) {
case AppListType.ALL:
size = allAppsIndexList.size();
break;
case AppListType.INSTALLED:
size = installAppsIndexList.size();
break;
case AppListType.CONTENT:
size = contentAppsIndexList.size();
break;
case AppListType.RUNNING:
// size = runningServices.size();
break;
default:
break;
}
return size;
}
/**
* Copy configuration file.
*/
private void copyFile() {
String file = CONFIG_FILE_NAME_TARGET + CONFIG_FILE_NAME;
File fl = new File(file);
if (!fl.exists()) {
copyAssetToData(CONFIG_FILE_NAME);
}
}
/**
* Copy configuration file from assets to data folder.
*
* @param strFilename
*/
private void copyAssetToData(String strFilename) {
// Open your local db as the input stream
try {
InputStream myInput = activity.getAssets().open(CONFIG_FILE_NAME);
String outFileName = CONFIG_FILE_NAME_TARGET + CONFIG_FILE_NAME;
// Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
// transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
try {
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
} finally {
// Close the streams
myOutput.flush();
myOutput.close();
}
myInput.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Read the configuration file with built-in application which will be
* displayed in Content list.
*/
private void readFile() {
configFile = new ArrayList<String>();
String path = CONFIG_FILE_NAME_TARGET + CONFIG_FILE_NAME;
File file = new File(path);
BufferedReader br;
try {
br = new BufferedReader(new FileReader(file));
String line;
try {
while ((line = br.readLine()) != null) {
configFile.add(line);
}
} finally {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Initialization of application list - create one list with all application
*/
public void initApplications() {
allAppsList = new ArrayList<AppItem>();
List<ApplicationInfo> apps = activity.getPackageManager()
.getInstalledApplications(0);
AppItem appItem;
for (int j = 0; j < apps.size(); j++) {
appItem = new AppItem();
appItem.setAppname((String) activity.getPackageManager()
.getApplicationLabel(apps.get(j)));
appItem.setAppPackage(apps.get(j).packageName);
if (isSystemPackage(apps.get(j))) {
if (configFile.contains(appItem.getAppPackage())) {
appItem.setAppListType(AppListType.CONTENT);
} else {
appItem.setAppListType(AppListType.NONE);
}
} else {
appItem.setAppListType(AppListType.INSTALLED);
}
if (!appItem.getAppname().toLowerCase().contains("android4tv")
&& !appItem.getAppname().toLowerCase().equals("tvservice")
&& !appItem.getAppname().toLowerCase()
.equals("iwedia_service")) {
allAppsList.add(appItem);
}
}
sortAppList();
createAppListIndexes();
}
/**
* Create lists with indexes from application list with all built-in and
* installed applications. allAppsIndexList - list with indexes of all
* applications from all application list. installAppsIndexList - list with
* indexes of downloaded applications from all application list.
* contentAppsIndexList - list with indexes of applications which will be
* displayed in Content list from all application list.
*/
public void createAppListIndexes() {
allAppsIndexList = new ArrayList<Integer>();
installAppsIndexList = new ArrayList<Integer>();
contentAppsIndexList = new ArrayList<Integer>();
for (int i = 0; i < allAppsList.size(); i++) {
allAppsIndexList.add(i);
if (allAppsList.get(i).getAppListType() == AppListType.INSTALLED) {
if (!allAppsList.get(i).getAppname().toLowerCase()
.contains("android4tv")) {
installAppsIndexList.add(i);
contentAppsIndexList.add(i);
}
} else if (allAppsList.get(i).getAppListType() == AppListType.CONTENT) {
contentAppsIndexList.add(i);
}
}
}
/**
* Sort items in application list in alphabetical order.
*/
public void sortAppList() {
Collections.sort(allAppsList, new Comparator<AppItem>() {
public int compare(AppItem object1, AppItem object2) {
return object1.getAppname().compareToIgnoreCase(
object2.getAppname());
}
});
}
/**
* Sort indexes in application list.
*
* @param list
*/
public void sortIndexAppList(ArrayList<Integer> list) {
Collections.sort(list, new Comparator<Integer>() {
public int compare(Integer object1, Integer object2) {
return object1.compareTo(object2);
}
});
}
/**
* Class PackageReceiver - Broadcast receiver which registers package
* broadcast intents - Intent.ACTION_PACKAGE_ADDED,
* Intent.ACTION_PACKAGE_REMOVED, Intent.ACTION_PACKAGE_RESTARTED etc.
*/
private class PackageReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
if (IWEDIAService.DEBUG) {
Log.e(LOG_TAG, "PackageReceiver " + " onReceive()");
}
Uri data = intent.getData();
if (data != null) {
String packageName = data.getSchemeSpecificPart();
String action = intent.getAction();
Log.e(LOG_TAG, "ACTION: " + action);
if (action != null) {
if (action.equals(Intent.ACTION_PACKAGE_ADDED)) {
if (IWEDIAService.DEBUG)
Log.e(LOG_TAG, "PackageReceiver "
+ "ACTION_PACKAGE_ADDED : " + packageName);
AppItem p = new AppItem();
ApplicationInfo appInfo = null;
try {
appInfo = activity.getPackageManager()
.getApplicationInfo(packageName, 0);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
p.setAppname((String) activity.getPackageManager()
.getApplicationLabel(appInfo));
if (appInfo != null) {
p.setAppPackage(appInfo.packageName);
}
p.setAppListType(AppListType.INSTALLED);
allAppsList.add(p);
sortAppList();
createAppListIndexes();
} else if (action.equals(Intent.ACTION_PACKAGE_CHANGED)) {
if (IWEDIAService.DEBUG)
Log.e(LOG_TAG, "PackageReceiver "
+ "ACTION_PACKAGE_CHANGED: " + packageName);
} else if (action.equals(Intent.ACTION_PACKAGE_INSTALL)) {
if (IWEDIAService.DEBUG)
Log.e(LOG_TAG, "PackageReceiver "
+ "ACTION_PACKAGE_INSTALL: " + packageName);
} else if (action
.equals(Intent.ACTION_PACKAGE_DATA_CLEARED)) {
if (IWEDIAService.DEBUG)
Log.e(LOG_TAG, "PackageReceiver "
+ "ACTION_PACKAGE_DATA_CLEARED: "
+ packageName);
} else if (action
.equals(Intent.ACTION_PACKAGE_FIRST_LAUNCH)) {
if (IWEDIAService.DEBUG)
Log.e(LOG_TAG, "PackageReceiver "
+ "ACTION_PACKAGE_FIRST_LAUNCH: "
+ packageName);
} else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) {
if (IWEDIAService.DEBUG)
Log.e(LOG_TAG, "PackageReceiver "
+ "ACTION_PACKAGE_REMOVED :" + packageName);
for (int i = 0; i < allAppsList.size(); i++)
if (allAppsList.get(i).getAppPackage()
.equals(packageName)) {
allAppsList.remove(i);
break;
}
createAppListIndexes();
SystemControl.broadcastUninstallFinished();
} else if (action.equals(Intent.ACTION_PACKAGE_REPLACED)) {
if (IWEDIAService.DEBUG)
Log.e(LOG_TAG, "PackageReceiver "
+ "ACTION_PACKAGE_REPLACED : "
+ packageName);
} else if (action.equals(Intent.ACTION_PACKAGE_RESTARTED)) {
if (IWEDIAService.DEBUG)
Log.e(LOG_TAG, "PackageReceiver "
+ "ACTION_PACKAGE_RESTARTED: "
+ packageName);
if (packageName.equals("com.iwedia.gui")) {
if (IWEDIAService.DEBUG)
Log.e(LOG_TAG, "SERVICE STOPPED "
+ "ACTION_PACKAGE_RESTARTED: "
+ packageName);
// IWEDIAService.getInstance().stopService(
// IWEDIAService.getInstance().getServiceIntent());
}
}
}
}
}
}
/**
* Check if is application with the application info built-in or downloaded.
*
* @param appInfo
* - application info.
* @return true if an application is built-in, else false.
*/
public boolean isSystemPackage(ApplicationInfo appInfo) {
return ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) ? true
: false;
}
/**
* Check if is application with the given package name (packageNameGlobal)
* built-in or downloaded.
*
* @return true if an application is built-in, else false.
*/
public boolean isSystemPackage() {
ApplicationInfo applicationInfo = null;
try {
applicationInfo = IWEDIAService.getContext().getPackageManager()
.getApplicationInfo(packageNameGlobal, 0);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
if (applicationInfo != null) {
return isSystemPackage(applicationInfo);
} else {
return false;
}
}
/**
* Check if the application is stopped.
*
* @return true if application is stopped, else false.
*/
public boolean isStopped() {
try {
appInfo = activity.getPackageManager().getApplicationInfo(
packageNameGlobal, 0);
} catch (NameNotFoundException e2) {
e2.printStackTrace();
}
if ((appInfo.flags & ApplicationInfo.FLAG_STOPPED) == 0) {
Log.e(LOG_TAG, "Active");
return false;
} else {
Log.e(LOG_TAG, "Stopped");
return true;
}
}
/**
* Gets list of running services.
*
* @return list of running services.
*/
public List<AppItem> getRunningServices() {
runningServices = new ArrayList<AppItem>();
ActivityManager am = (ActivityManager) IWEDIAService.getInstance()
.getSystemService(IWEDIAService.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> rs = am.getRunningServices(50);
AppItem appItem;
for (int i = 0; i < rs.size(); i++) {
ActivityManager.RunningServiceInfo rsi = rs.get(i);
if (!rsi.process.contains("phone")
&& !rsi.process.contains("systemui")
&& !rsi.service.getPackageName().equals(
"com.iwedia.service")
&& !rsi.service.getPackageName().equals(
"com.rtrk.comedia.service")
&& !rsi.service.getPackageName().contains("Google")
&& !rsi.service.getPackageName().contains("google")) {
appItem = new AppItem();
appItem.setAppListType(AppListType.RUNNING);
appItem.setAppname(getProcessName(rsi.service.getPackageName()));
appItem.setAppPackage(rsi.service.getPackageName());
appItem.setAppClass(rsi.service.getClassName());
runningServices.add(appItem);
}
}
if (rs.size() == 0) {
return null;
}
return runningServices;
}
/**
* Gets process name with the given package name.
*
* @param packageName
* - package name.
* @return process name.
*/
private String getProcessName(String packageName) {
final PackageManager pm = IWEDIAService.getContext()
.getPackageManager();
ApplicationInfo ai;
try {
ai = pm.getApplicationInfo(packageName, 0);
} catch (final NameNotFoundException e) {
ai = null;
}
final String processName = (String) (ai != null ? pm
.getApplicationLabel(ai) : packageName);
return processName;
}
/**
* Force stop an application with the given package name
* (packageNameGlobal).
*
* @return true if everything is OK, else false
*/
public boolean forceStop() {
try {
ActivityManagerNative = Class
.forName("android.app.ActivityManagerNative");
IActivityManager = Class.forName("android.app.IActivityManager");
getDefault = ActivityManagerNative.getMethod("getDefault",
(Class<?>[]) null);
am = IActivityManager.cast(getDefault.invoke(ActivityManagerNative,
(Object[]) null));
Class<?>[] param = new Class[] { String.class };
forceStopPackage = am.getClass().getMethod("forceStopPackage",
param);
forceStopPackage.invoke(am, new Object[] { packageNameGlobal });
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* Uninstall the downloaded application.
*
* @return true if everything is OK, else false.
*/
public boolean uninstall() {
try {
pom.uninstallPackage(packageNameGlobal);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* Gets application size information - application (code) size, data size,
* cache size, external data size etc, external cache size etc.
*/
public void getAppSizeInfo() {
try {
pom.getPackageSizeInfo(packageNameGlobal);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Enable or disable built-in applications. If application is enabled, this
* function disables application with the given package (packageNameGlobal),
* else enables.
*
* @return true if everything is OK, else false.
*/
public boolean enable() {
try {
if (isEnabled()) {
activity.getPackageManager()
.setApplicationEnabledSetting(
packageNameGlobal,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER,
0);
} else {
activity.getPackageManager().setApplicationEnabledSetting(
packageNameGlobal,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
}
return true;
} catch (Exception e) {
return false;
}
}
/**
* Check if is built-in application with the given package name
* (packageNameGlobal) enabled or disabled.
*
* @return true if application is enabled, else false.
*/
public boolean isEnabled() {
if (activity.getPackageManager().getApplicationEnabledSetting(
packageNameGlobal) == PackageManager.COMPONENT_ENABLED_STATE_ENABLED
|| activity.getPackageManager().getApplicationEnabledSetting(
packageNameGlobal) == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
return true;
} else if (activity.getPackageManager().getApplicationEnabledSetting(
packageNameGlobal) == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
|| activity.getPackageManager().getApplicationEnabledSetting(
packageNameGlobal) == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
return false;
} else {
return false;
}
}
/**
* Delete application cache files.
*/
public void deleteApplicationCacheFiles() {
try {
pom.deleteApplicationCacheFiles(packageNameGlobal);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Delete application user data - all files, accounts, databases etc.
*/
public void clearApplicationUserData() {
try {
pom.clearApplicationUserData(packageNameGlobal);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Gets list of application permissions.
*
* @return list of application permissions.
*/
public List<AppPermission> getAppPermissions() {
appSecurityPermissions = new AppSecurityPermissions(
IWEDIAService.getContext(), packageNameGlobal);
if (appSecurityPermissions.getPermissionCount() > 0) {
appPermissions = appSecurityPermissions.getPermissions();
} else {
appPermissions = null;
}
return appPermissions;
}
/**
* Check if is application with the given package name (packageNameGlobal)
* set to open by default for some actions.
*
* @return true if is application with the given package name
* (packageNameGlobal) default application, otherwise false.
*/
public boolean isDefault() {
prefActList = new ArrayList<ComponentName>();
intentList = new ArrayList<IntentFilter>();
try {
activity.getPackageManager().getPreferredActivities(intentList,
prefActList, packageNameGlobal);
if (prefActList.size() > 0) {
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* Clear application's default actions.
*
* @return true if everything is OK, else false.
*/
public boolean clearDefaults() {
try {
activity.getPackageManager().clearPackagePreferredActivities(
packageNameGlobal);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private class ShutdownReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
Log.e(LOG_TAG, "SHUT DOWN" + action);
}
}
public void stopService(String packegeName, String className) {
IWEDIAService.getInstance().stopService(
new Intent().setComponent(new ComponentName(packegeName,
className)));
}
}