How do I start a service based on a ServiceInfo object? - android

In my app, I query for the list of services that have a specific Category in their intent-filters. This goes just fine, I get back a List containing ResolveInfo objects. In these ResolveInfos I found the "serviceInfo" field, that's supposed to describe the details of a found service.
Now how do I construct an Intent from the serviceInfo, that can start the found service?
My code now is like this:
PackageManager pm = getApplicationContext().getPackageManager();
Intent i = new Intent();
i.setAction("<my custom action>");
i.addCategory("<my custom category>");
List<ResolveInfo> l = pm.queryIntentServices(i, 0);
gatherAgentNum = l.size();
if(gatherAgentNum > 0){
for(ResolveInfo info : l){
Intent i2 = new Intent(this, info.serviceInfo.getClass());
i2.putExtra(BaseAgent.KEY_RESULT_RECEIVER, new GatherResult(mHandler));
startService(i2);
}
}
This's obviously wrong, the "info.serviceInfo.getClass()" just returns the serviceInfo object's class. Could anyone help me with this?
Thank you
Edit: The solution (at least the one I used):
PackageManager pm = getApplicationContext().getPackageManager();
Intent i = new Intent();
i.setAction("<my action>");
i.addCategory("<my category>");
List<ResolveInfo> l = pm.queryIntentServices(i, 0);
if(l.size() > 0){
for(ResolveInfo info : l){
ServiceInfo servInfo = info.serviceInfo;
ComponentName name = new ComponentName(servInfo.applicationInfo.packageName, servInfo.name);
Intent i2 = new Intent();
i2.setComponent(name);
startService(i2);
}
}

Have you taken a look at :
http://developer.android.com/reference/android/content/pm/ServiceInfo.html
http://developer.android.com/reference/android/content/pm/PackageItemInfo.html#packageName
http://developer.android.com/reference/android/content/pm/ApplicationInfo.html
I guess you could try to replace the getClass class with .packageName - and use packageManager.getLaunchIntentForPackage(String)
Also take a look at:
http://developer.android.com/reference/android/content/pm/PackageManager.html
queryIntentServices, resolveService

Related

How to get Package name from activity name

I use the code below to get the launcher activity name belongs to specific package name:
Intent intent = new Intent();
intent.setPackage(aPackageName);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ResolveInfo result = getPackageManager().resolveActivity(intent, 0);
I save result.activityInfo.name to shared preference
Later I want to start this activity, but how to get its package name?
or, Is it possible to start this activity without knowing the package name it belongs to?
Intent launchIntent =
getPackageManager().getLaunchIntentForPackage(How to get the package name);
if(launchIntent != null){
startActivity(launchIntent);
}
Knowing that the activity(s) name(s) that I save are not mine.
To answer this,
How to get Package name from activity name
If you want to find the package name from the Launcher activity name, please check the following,
String activityName = "TermuxActivity";
PackageManager pm = getPackageManager();
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> activityList = pm.queryIntentActivities(intent, 0);
Collections.sort(activityList, new ResolveInfo.DisplayNameComparator(pm));
for (ResolveInfo temp : activityList) {
if(temp.activityInfo.name.endsWith(activityName)){
Log.i("ActivityCheck", " Activity : " +temp.activityInfo.name+ " package name: " +temp.activityInfo.packageName);
}
}
Output:
ActivityCheck: Activity : com.termux.app.TermuxActivity package name: com.termux
Try this :-
public static String PACKAGE_NAME;
PACKAGE_NAME = getApplicationContext().getPackageName();
You can use this given below code to get package name of application
In Java supported code:
String packageName=this.getPackageName(); // where this represent the context
In Kotlin supported code:
var packageName:String=this.packageName // where this represent the context
Use the following code to get the launcher activity of all packages from your installed apps:
final PackageManager pm = getPackageManager();
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> appList = pm.queryIntentActivities(mainIntent, 0);
Collections.sort(appList, new ResolveInfo.DisplayNameComparator(pm));
for (ResolveInfo temp : appList) {
Log.v("my logs", "package and activity name = "
+ temp.activityInfo.packageName + " "
+ temp.activityInfo.name);
}
The only reliable way was Vladyslav Matviienko suggestion, which is storing package name along with each activity name in a hashmap to be like .. Thank you all for your help.

How to mock packageManager.queryIntentActivities in Robolectric 3.4.2?

I have:
PackageManager packageManager = androidContext.getApplicationContext().getPackageManager();
final List appList = packageManager.queryIntentActivities(createIntentToLauncherActivity(), 0);
private Intent createIntentToLauncherActivity() {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
return intent;
}
In source code I can mock packageManager but I am getting exception for packageManager.queryIntentActivities(createIntentToLauncherActivity(), 0);.
I am getting empty applist but I need to set with details like
log.d("Package Name: " + appInfo.activityInfo.packageName);
log.d("Activity Name: " + appInfo.activityInfo.name);
log.d("Process Name: " + appInfo.activityInfo.processName);
I used
List appList = new ArrayList();
ResolveInfo resolveInfo = new ResolveInfo();
resolveInfo.isDefault = true;
ActivityInfo activityInfo = new ActivityInfo();
activityInfo.packageName = "jp.co.ricoh.advop.simplecopy";
resolveInfo.activityInfo = new ActivityInfo();
resolveInfo.activityInfo = activityInfo;
resolveInfo.activityInfo.name = "Example";
appList.add(resolveInfo);
When I add conditions like below to mock queryIntentActivities like below:
when(shadowApplicationPackageManager.queryIntentActivities(createIntentToLauncherActivity(), 0)).thenReturn(appList);
After setting this I am getting
java.lang.reflect.InvocationTargetException
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
ArrayList cannot be returned by toString()`enter code here`
toString() should return String
How can I fix this?
First, you have to decide if your test will be Robolectric one without mocking PackageManager or it will be JVM and you mock it with Mockito.
If you go with Robolectric then you need just instruct ShadowPackageManager:
PackageManager pm = RuntimeEnvironment.applicaition.getPackageManager();
ShadowPackageManager spm = shadowOf(pm);
spm.addResolveInfoForIntent(intent, list);
Unfortunately, provided parts of your code don't show where exactly you're getting the error.
I also recommend avoiding Robolectric because of the running time.

How can I get OS default apps in android

I'm developing a launcher app, I need to retrieve an Android OS default Phone app, Browser app and SMS apps', application Info (Application name, Package name, Launcher icon). Following code is used to get all launchable applications.
private static List<ApplicationInfo> getInstalledApps(Context context, PackageManager pm) {
List<ApplicationInfo> installedApps = context.getPackageManager().getInstalledApplications(0);
List<ApplicationInfo> laughableInstalledApps = new ArrayList<>();
for(int i =0; i<installedApps.size(); i++){
if(pm.getLaunchIntentForPackage(installedApps.get(i).packageName) != null){
laughableInstalledApps.add(installedApps.get(i));
}
}
return laughableInstalledApps;
}
After spending some time with the code, I found a way get what I wanted.
Default Dial App
Intent mainIntent = new Intent(Intent.ACTION_DIAL, null);
mainIntent.addCategory(Intent.CATEGORY_DEFAULT);
List<ResolveInfo> pkgAppsList = getPackageManager().queryIntentActivities(mainIntent, 0);
ActivityInfo info = pkgAppsList.get(0).activityInfo;
Default SMS App
String smsPkgName = Telephony.Sms.getDefaultSmsPackage(context);
ApplicationInfo info = getPackageManager().getApplicationInfo(smsPkgName, 0);
Default Browser App
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://"));
ResolveInfo resolveInfo = getPackageManager().resolveActivity(browserIntent,
PackageManager.MATCH_DEFAULT_ONLY);
ActivityInfo info = resolveInfo.activityInfo;
Try with PackageManager#getPreferredActivities(java.util.List, java.util.List, java.lang.String), where the first parameter is a list of IntentFilter, which you would like to get default apps for. Then the answer is written in list passed as second parameter.
Here are some common intents for which you might try to find default apps.

How to get metadata from ActivityInfo?

I want to read activity metadata from another app. I have cole like this:
PackageManager packageManager = getPackageManager();
Intent intent = new Intent(MY_ACTION);
List<ResolveInfo> pluginsInfo = packageManager.queryIntentActivities(intent, PackageManager.GET_RESOLVED_FILTER);
for (ResolveInfo plugin : pluginsInfo) {
ResolveInfo info = plugin;
ActivityInfo aInfo = info.activityInfo;
Bundle metadata = aInfo.metaData;
}
And sometimes it works good, but sometimes metadata is null. On same emulator and same app version. Is there other way to do this?
And answer is simple:
packageManager.queryIntentActivities(intent, PackageManager.GET_RESOLVED_FILTER | PackageManager.GET_META_DATA);

Android launch browser without specifying a URL

How would one go about launching the browser from an activity without specifying a url. I would like to open the browser so the user can continue browsing without changing the page they were on?
SOLUTION:
Answer below was correct and worked, but to be more specific for future readers, here is the working code:
Intent i = new Intent();
i.setAction(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_LAUNCHER);
i.setAction("com.android.browser");
ComponentName comp = new ComponentName("com.android.browser", "com.android.browser.BrowserActivity");
i.setComponent(comp);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
Thanks!
Use Intent#setComponent() to set the Browser's package and class name. Then start the activity.
In case it (the ComponentName("com.android.browser", "com.android.browser.BrowserActivity")) changes in the future, you may try something like the following code:
public static ComponentName getDefaultBrowserComponent(Context context) {
Intent i = new Intent()
.setAction(Intent.ACTION_VIEW)
.setData(new Uri.Builder()
.scheme("http")
.authority("x.y.z")
.appendQueryParameter("q", "x")
.build()
);
PackageManager pm = context.getPackageManager();
ResolveInfo default_ri = pm.resolveActivity(i, 0); // may be a chooser
ResolveInfo browser_ri = null;
List<ResolveInfo> rList = pm.queryIntentActivities(i, 0);
for (ResolveInfo ri : rList) {
if (ri.activityInfo.packageName.equals(default_ri.activityInfo.packageName)
&& ri.activityInfo.name.equals(default_ri.activityInfo.name)
) {
return ri2cn(default_ri);
} else if ("com.android.browser".equals(ri.activityInfo.packageName)) {
browser_ri = ri;
}
}
if (browser_ri != null) {
return ri2cn(browser_ri);
} else if (rList.size() > 0) {
return ri2cn(rList.get(0));
} else if (default_ri == null) {
return null;
} else {
return ri2cn(default_ri);
}
}
private static ComponentName ri2cn(ResolveInfo ri) {
return new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
}
Basically, here I construct an intent to view a dummy http page, get the list of activities that may handle the intent, compare it to the default handler returned by resolveActivity() and return something. I do not need to check if there's a launcher MAIN action (my code uses the VIEW action), but you probably should.
this answer may help. from How to open the default android browser without specifying an URL?
PackageManager pm = getPackageManager();
Intent queryIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));
ActivityInfo af = queryIntent.resolveActivityInfo(pm, 0);
Intent launchIntent = new Intent(Intent.ACTION_MAIN);
launchIntent.setClassName(af.packageName, af.name);
startActivity(launchIntent);

Categories

Resources