I have a function to get running services:
public ArrayList<String> getRunningServices() {
ActivityManager activityMg = (ActivityManager)context.getSystemService(context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> serviceList = activityMg.getRunningServices(100);
ArrayList<String> serviceName = new ArrayList<String>();
for (int i=0; i<serviceList.size(); i++) {
ActivityManager.RunningServiceInfo currentService = serviceList.get(i);
boolean serviceNam = currentService.started;
if (serviceNam == true) {
serviceName.add(currentService.service.getPackageName());
}
}
return serviceName;
}
Now I want to run one of these services if it is stopped.
To run an installed app I have to use intent like this code:
Intent intent = context.getPackageManager().getLaunchIntentForPackage(nameOfPakage);
context.startActivity(intent);
But I want to just run a service of this app or another one.
I have a String name of package of app and i want start its service.
Is it possible?
Hi there below is to start a service from another application.
Intent intent = new Intent();
String pkg = currentService.service.getPackageName();
String cls = currentService.service.getPackageName() + "." + currentService.service.getClassName();
intent.setComponent(new ComponentName(pkg, cls));
startService(intent);
Related
What I do
I'm retrieving a list of all installed apps like following (for a launcher like app):
PackageManager pm = context.getPackageManager();
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null)
.addCategory(Intent.CATEGORY_LAUNCHER);
// flag PackageManager.GET_RESOLVED_FILTER will set ResolveInfo.filter (not documented, but tested)
// many examples use flag == 0, but then the filter is always null
List<ResolveInfo> ril = pm.queryIntentActivities(mainIntent, PackageManager.GET_RESOLVED_FILTER);
if (ril != null) {
for (ResolveInfo ri : ril) {
// I need this info!
// ri.isDefault is always false...
boolean isDefault = ri.isDefault || ril.filter.hasCategory(Intent.CATEGORY_DEFAULT);
}
}
So far, this works. But some apps like samsungs phone app do not respect that they should only flag one activity with Intent.CATEGORY_DEFAULT. Here's what the categories for the two activities in samsung's app look like:
ActivityInfo{cd007eb com.android.contacts.activities.PeopleActivity}
filter:
0 = "android.intent.category.DEFAULT"
1 = "android.intent.category.LAUNCHER"
2 = "android.intent.category.BROWSABLE"
3 = "android.intent.category.APP_CONTACTS"
ActivityInfo{3e9ba8d com.android.dialer.DialtactsActivity}
filter:
0 = "android.intent.category.DEFAULT"
1 = "android.intent.category.LAUNCHER"
2 = "android.intent.category.BROWSABLE"
Requirements
I need a list of all activities a launcher like app like mine can launch
I need the info if a ResolveInfo is the one that is launched if I use the apps package name only like if I use the intent retrieved by following command: pm.getLaunchIntentForPackage(packageName). This one is what I call the default launch intent in this post
Question
How can I find out reliably if a ResolveInfo belongs to the default launch intent?
You can use the queryIntentActivities as follows:
PackageManager pm = context.getPackageManager();
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null)
.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> ril = pm.queryIntentActivities(mainIntent, PackageManager.MATCH_DEFAULT_ONLY);
Based on the documentation for MATCH_DEFAULT_ONLY:
Resolution and querying flag: if set, only filters that support the
CATEGORY_DEFAULT will be considered for matching. This is a synonym
for including the CATEGORY_DEFAULT in your supplied Intent.
SOLUTION
This solution is useable as long as you assume that only some apps register multiple default activities.
get all ResolveInfos like in my question
create a HashMap and insert package names and number of entries in list
use the HashMap to determine if you even need to check if the ResolveInfo belongs to the default activity or not
if you need to check, make the slow check for this ResolveInfo
Code
List<ResolveInfo> ril = ...;
HashMap<String, Integer> packageCountMap = getPackageCountMap(uniqueRil);
for (ResolveInfo ri :: ril) {
boolean isDefault = isDefaultIntentForPhoneApp(packageCountMap, ri);
// use this info...
}
Helper function:
public static HashMap<String, Integer> getPackageCountMap(List<ResolveInfo> ril) {
HashMap<String, Integer> map = new HashMap<>();
ResolveInfo ri;
Integer count;
if (ril != null) {
for (int i = 0; i < ril.size(); i++) {
ri = ril.get(i);
count = map.get(ri.activityInfo.packageName);
if (count == null) {
count = 1;
} else {
count++;
}
map.put(ri.activityInfo.packageName, count);
}
}
return map;
}
public static boolean isDefaultIntentForPhoneApp(PackageManager pm, HashMap<String, Integer> packageCountMap, ResolveInfo ri) {
boolean isDefault;
// count how often the package name exists => 1x => then the activity must be the default one, no need to do any check
Integer count = packageCountMap.get(ri.activityInfo.packageName);
if (count == null || count <= 1) {
isDefault = true;
}
// otherwise get default activity and compare it
else {
Intent i = pm.getLaunchIntentForPackage(packageName);
ComponentName cn = i.resolveActivity(pm);
isDefault = cn != null && cn.getClassName().equals(ri.activityInfo.name);
}
return isDefault;
}
After starting default calculator and hitting back navigation, the user is returned to a different activity rather than the calling activity. When the user clicks the calculator button, the devices default calculator opens. Upon invoking onBackPressed, the user is returned to a different activity within the app that they should not be going to. How can I make sure that the user is returned to the calling activity? Here's my code and what I have tried:
public static void openByName(Context context, String name){
ArrayList<HashMap<String,Object>> items =new ArrayList<HashMap<String,Object>>();
final PackageManager pm = context.getPackageManager();
List<PackageInfo> packs = pm.getInstalledPackages(0);
for (PackageInfo pi : packs) {
if( pi.packageName.toLowerCase().contains(name)){
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("appName", pi.applicationInfo.loadLabel(pm));
map.put("packageName", pi.packageName);
items.add(map);
}
}
if(items.size()>=1){
String packageName = (String) items.get(0).get("packageName");
Log.d(TAG, "PackageName: " + packageName);
Intent i = pm.getLaunchIntentForPackage(packageName);
if (i != null)
context.startActivity(i);
}
else{
// Application not found
Toaster.make(context, name + " not found");
}
}
After different method attempts, I had to use this way because it otherwise wouldn't work on some devices.
I am trying to find out the data usage on Android on a per-application basis. Something like Android Data Usage Apps and Quota / Cap Monitor Widgets: never get charged extra for data or get capped again!.
I looked at Stack Overflow question How to go about detecting data usage in the Android environment.
But it's not been of much help.
ActivityManager activityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
ActivityManager.MemoryInfo mInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo( mInfo );
List<RunningAppProcessInfo> listOfRunningProcess = activityManager.getRunningAppProcesses();
Log.d(TAG, "XXSize: " + listOfRunningProcess.size());
for (RunningAppProcessInfo runningAppProcessInfo : listOfRunningProcess) {
if (runningAppProcessInfo.uid > 1026)
{
Log.d(TAG, "ANS " + runningAppProcessInfo.processName +
" Id :" + runningAppProcessInfo.pid +
" UID: " + runningAppProcessInfo.uid);
}
}
I tried the above code as suggested by Akos Cz. However all the UIDs are numbers, unlike app_79 as you have mentioned above. Is this all right?
The following links should help you figure out how to programmatically determine the data usage per application.
Create a network monitor using Android's TrafficStats class
Android Traffic Statistics Inside
You will need to implement your code to use the TraficStats API and track the number of bytes sent/received per UID (application).
Use this method after create a new class PackageInformationTotal.
public void getPakagesInfoUsingHashMap() {
final PackageManager pm = getPackageManager();
// get a list of installed apps.
List<ApplicationInfo> packages = pm.getInstalledApplications(0);
// loop through the list of installed packages and see if the selected
// app is in the list
for (ApplicationInfo packageInfo : packages) {
// get the UID for the selected app
UID = packageInfo.uid;
String package_name = packageInfo.packageName;
ApplicationInfo app = null;
try {
app = pm.getApplicationInfo(package_name, 0);
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String name = (String) pm.getApplicationLabel(app);
Drawable icon = pm.getApplicationIcon(app);
// internet usage for particular app(sent and received)
double received = (double) TrafficStats.getUidRxBytes(UID)
/ (1024 * 1024);
double send = (double) TrafficStats.getUidTxBytes(UID)
/ (1024 * 1024);
double total = received + send;
if(total>0)
{
PackageInformationTotal pi=new PackageInformationTotal();
pi.name=name;
pi.packageName=package_name;
pi.icon=icon;
pi.totalMB=String.format( "%.2f", total )+" MB";
pi.individual_mb=String.format( "%.2f", total );
totalData+=Double.parseDouble(String.format( "%.2f", total ));
dataHash.add(pi);
Log.e(name,String.format( "%.2f", total )+" MB");
}
}
Editor edit=shared.edit();
edit.putString("Total",String.format( "%.2f", totalData));
edit.commit();
}
After that you can track all process usages in MB.
Prorammatically:
You can declare the intent filter for the ACTION_MANAGE_NETWORK_USAGE action (introduced in Android 4.0) to indicate that your application defines an activity that offers options to control data usage. ACTION_MANAGE_NETWORK_USAGE shows settings for managing the network data usage of a specific application. When your app has a settings activity that allows users to control network usage, you should declare this intent filter for that activity.
Check this out for more information about managing data usage manage usage per application.
The proper definition of ACTION_MANAGE_NETWORK_USAGE is you can see here.
public class Main extends Activity {
private Handler mHandler = new Handler();
private long mStartRX = 0;
private long mStartTX = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mStartRX = TrafficStats.getTotalRxBytes();
mStartTX = TrafficStats.getTotalTxBytes();
if (mStartRX == TrafficStats.UNSUPPORTED || mStartTX == TrafficStats.UNSUPPORTED) {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Uh Oh!");
alert.setMessage("Your device does not support traffic stat monitoring.");
alert.show();
} else {
mHandler.postDelayed(mRunnable, 1000);
}
}
private final Runnable mRunnable = new Runnable() {
public void run() {
TextView RX = (TextView)findViewById(R.id.RX);
TextView TX = (TextView)findViewById(R.id.TX);
long rxBytes = TrafficStats.getTotalRxBytes()- mStartRX;
RX.setText(Long.toString(rxBytes));
long txBytes = TrafficStats.getTotalTxBytes()- mStartTX;
TX.setText(Long.toString(txBytes));
mHandler.postDelayed(mRunnable, 1000);
}
};
}
You can also checkout https://github.com/commonsguy/cw-andtuning/tree/master/TrafficMonitor
This snippet also works for those actually running apps in your device
final PackageManager pm = getPackageManager();
ActivityManager activityManager = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
//final List<ActivityManager.RunningTaskInfo> recentTasks = activityManager.getRunningTasks(Integer.MAX_VALUE);
for (int i = 0; i < appProcesses.size(); i++) {
Log.d("Executed app", "Application executed : " + appProcesses.get(i).processName + "\t\t ID: " + appProcesses.get(i).pid + "");
// String packageName = activityManager.getRunningTasks(1).get(0).topActivity.getPackageName();
//String packageName = appProcesses.get(i)..getPackageName();
ApplicationInfo app = null;
try {
app = pm.getApplicationInfo(appProcesses.get(i).processName, 0);
if ((app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 1) {
//it's a system app, not interested
} else if ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 1) {
//Discard this one
//in this case, it should be a user-installed app
} else {
// tx = TrafficStats.getUidTxBytes(app.uid);
//rx = TrafficStats.getUidRxBytes(app.uid);
long delta_rx = TrafficStats.getUidRxBytes(app.uid) - rx;
long delta_tx = TrafficStats.getUidTxBytes(app.uid) - tx;
}
}
To access an individual app stats you will need the uid of that app, which is an int value assigned by the system to each app at install time.
PackageManager packageManager = context.getPackageManager();
ApplicationInfo info = packageManager.getApplicationInfo("com.example.app", 0);
int packageUid = info.uid;
To get all Rx and Tx bytes of Mobile for package :
NetworkStats.Bucket bucket = networkStatsManager.queryDetailsForUid(ConnectivityManager.TYPE_MOBILE, getSubscriberId(context, ConnectivityManager.TYPE_MOBILE), 0, System.currentTimeMillis(),packageUid);
long rxBytes = 0L;
long txBytes = 0L;
NetworkStats.Bucket bucket = new NetworkStats.Bucket();
while (networkStats.hasNextBucket()) {
networkStats.getNextBucket(bucket);
rxBytes += bucket.getRxBytes();
txBytes += bucket.getTxBytes();
}
networkStats.close();
For more clarification about this, check:
How do I programmatically show data usage of all applications?
After a long struggle,I am able to find the Solution for getting data over any interface for each installed Application in android
device.
As Android provides TrafficStats Apis but these APIs are providing comple Data stastics for each app uid since device boot and Even
APIs are not supporting to get the data over any interface for a particular application.
Even if we rely over TraffiucStates APIS ,we get a new data statstics for each Application.
So I thought to use the hidden APIs to USe this..
Here I am mentioning the Steps to get the data statstics for each application over any Interface in Android...
Estabalish a "INetworkStatsSession" session
#import android.net.INetworkStatsSession;
INetworkStatsSession mStatsSession = mStatsService.openSession();
Create a Network Templeate according to interafce which you want to measure..
#import static android.net.NetworkTemplate.buildTemplateEthernet;
#import static android.net.NetworkTemplate.buildTemplateMobile3gLower;
#import static android.net.NetworkTemplate.buildTemplateMobile4g;
#import static android.net.NetworkTemplate.buildTemplateMobileAll;
#import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
#import android.net.NetworkTemplate;
private NetworkTemplate mTemplate;
mTemplate = buildTemplateMobileAll(getActiveSubscriberId(this
.getApplicationContext()));
GetActive SubcriberID:
private static String getActiveSubscriberId(Context context) {
final TelephonyManager tele = TelephonyManager.from(context);
final String actualSubscriberId = tele.getSubscriberId();
return SystemProperties.get(TEST_SUBSCRIBER_PROP, actualSubscriberId);
}
Collect the network HIStory of respective application byt passing application UIDs...
private NetworkStatsHistory collectHistoryForUid(NetworkTemplate template,
int uid, int set) throws RemoteException {
final NetworkStatsHistory history = mStatsSession.getHistoryForUid(
template, uid, set, TAG_NONE, FIELD_RX_BYTES | FIELD_TX_BYTES);
return history;
}
Get the total Consumption data:
public void showConsuption(int UID){
NetworkStatsHistory history = collectHistoryForUid(mTemplate, UID,
SET_DEFAULT);
Log.i(DEBUG_TAG, "load:::::SET_DEFAULT:.getTotalBytes:"+ Formatter.formatFileSize(context, history.getTotalBytes()));
history = collectHistoryForUid(mTemplate, 10093,
SET_FOREGROUND);
Log.i(DEBUG_TAG, "load::::SET_FOREGROUND::.getTotalBytes:"+ Formatter.formatFileSize(context, history.getTotalBytes()));
history = collectHistoryForUid(mTemplate, 10093,
SET_ALL);
Log.i(DEBUG_TAG, "load::::SET_ALL::.getTotalBytes:"+ Formatter.formatFileSize(context, history.getTotalBytes()));
}
I would like to launch com.google.android.feedback.FeedbackActivity for my application. Like it happens in Hangouts application.
Does anyone knows which extras I need to pass to do so?
So it seems that this is possible, bur report is not visible in Developer console.
#TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
protected Intent prepareIcsFeedbackIntent(Activity activity, PackageManager packageManager) {
ApplicationErrorReport localApplicationErrorReport = new ApplicationErrorReport();
localApplicationErrorReport.packageName = activity.getPackageName();
localApplicationErrorReport.type = 11;
localApplicationErrorReport.installerPackageName = packageManager.getInstallerPackageName(
localApplicationErrorReport.packageName);
return getAppErrortIntent().putExtra(Intent.EXTRA_BUG_REPORT, localApplicationErrorReport);
}
#TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
protected Intent getAppErrortIntent() {
Intent localIntent = new Intent(Intent.ACTION_APP_ERROR)
.addCategory(Intent.CATEGORY_DEFAULT)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return localIntent;
}
Although it's not exactly the same, you can programmatically invoke a crash-report-dialog:
ApplicationErrorReport report = new ApplicationErrorReport();
report.packageName = report.processName = getApplication()
.getPackageName();
report.time = System.currentTimeMillis();
report.type = ApplicationErrorReport.TYPE_CRASH;
report.systemApp = false;
ApplicationErrorReport.CrashInfo crash = new ApplicationErrorReport.CrashInfo();
crash.exceptionClassName = e.getClass().getSimpleName();
crash.exceptionMessage = e.getMessage();
StringWriter writer = new StringWriter();
PrintWriter printer = new PrintWriter(writer);
e.printStackTrace(printer);
crash.stackTrace = writer.toString();
StackTraceElement stack = e.getStackTrace()[0];
crash.throwClassName = stack.getClassName();
crash.throwFileName = stack.getFileName();
crash.throwLineNumber = stack.getLineNumber();
crash.throwMethodName = stack.getMethodName();
report.crashInfo = crash;
Intent intent = new Intent(Intent.ACTION_APP_ERROR);
intent.putExtra(Intent.EXTRA_BUG_REPORT, report);
startActivity(intent);
More information here: http://blog.tomtasche.at/2012/10/use-built-in-feedback-mechanism-on.html
Just re-create that layout on a .xml file and create a Class that extends FragmentActivity (as the Google Hangouts App seems to do) or create a Class that extends DialogFragment to handle its logic.
I am trying to make a program that shows all the active applications.
I searched everywhere but could only find code that shows the package name only.
It would be of great help if you masters can tell me how to display all the active application name
Did you try using ActivityManager.getRunningAppProcesses()?
Here is the sample code for retrieving names:ActivityManager am = (ActivityManager)this.getSystemService(ACTIVITY_SERVICE);
List l = am.getRunningAppProcesses();
Iterator i = l.iterator();
PackageManager pm = this.getPackageManager();
while(i.hasNext()) {
ActivityManager.RunningAppProcessInfo info = (ActivityManager.RunningAppProcessInfo)(i.next());
try {
CharSequence c = pm.getApplicationLabel(pm.getApplicationInfo(info.processName, PackageManager.GET_META_DATA));
Log.w("LABEL", c.toString());
}catch(Exception e) {
//Name Not FOund Exception
}
}
If you are getting the package name, you should be able to get additional information about the application using the PackageManager:
http://developer.android.com/reference/android/content/pm/PackageManager.html
There are direct methods for getting the application icon, ApplicationInfo and ActivityInfo objects. Off the top of my head I don't know which one would direct you to the readable name, but if its not directly accessible through one of the methods here, it should be accessible from the application resources (also accessible from this class).
If you are writing a service and want to update the current "foreground app" at regular intervals like I did, DO NOT be tempted to get the ActivityManager instance in the onCreate() of your service and re-use it when updating the current app name:
public class MyService extends Service implements {
ActivityManager mActivityManager;
#Override public void onCreate() {
mActivityManager = (ActivityManager)getSystemService(ACTIVITY_SERVICE ); }
String getForegroundAppName() {
String appname;
List <RunningAppProcessInfo> l;
l = mActivityManager.getRunningAppProcesses();
while( i.hasNext() ) {
if ( info.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND && !isRunningService(info.processName) {
currentApp = info;
break;
}
}
if ( currentApp != null ) {
try {
CharSequence c = pm.getApplicationLabel(pm.getApplicationInfo(currentApp.processName, PackageManager.GET_META_DATA ));
appname = c.toString();
}
return appname;
}
}
Don't do this. It causes a memory leak resulting in numerous GC_CONCURRENT errors every time it's called. I don't know the real reason behind this but it's much cleaner to get the ApplicationManager instance each time you use it like this:
public class MyService extends Service implements {
#Override public void onCreate() {... }
String getForegroundAppName() {
ActivityManager mActivityManager;
String appname;
mActivityManager = (ActivityManager)getSystemService(ACTIVITY_SERVICE );
List <RunningAppProcessInfo> l;
l = mActivityManager.getRunningAppProcesses();
while( i.hasNext() ) {
if ( info.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND && !isRunningService(info.processName) {
currentApp = info;
break;
}
}
if ( currentApp != null ) {
try {
CharSequence c = pm.getApplicationLabel(pm.getApplicationInfo(currentApp.processName, PackageManager.GET_META_DATA ));
appname = c.toString();
}
return appname;
}
}