Optimal way to create shorcut for other package activity - java

I'm trying to create programmability a home shortcut for any installed application.
Considering that the only thing I would have available would the application name, let's say for example the Calculator com.android.calculator2 (1.5).
I'm using current code bellow, shortcut is created successfully but activity cannot be launched from shortcut (wrong activity class name I guess) and also sometimes the icon seems to be corrupted.
Also add com.android.launcher.permission.INSTALL_SHORTCUT to manifest.xml.
Is there a optimal way to achieved this?
String appName = "com.android.calculator2";
Context newAppContext = null;
// Get other package context
try {
newAppContext =
context.createPackageContext(appName, Context.CONTEXT_IGNORE_SECURITY);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
// Create shortcut
if(newAppContext != null) {
// Get Application Name
PackageManager pm = context.getPackageManager();
ApplicationInfo ai;
try {
ai = pm.getApplicationInfo(appName, 0);
} catch (final NameNotFoundException e) {
ai = null;
}
// Get application label
String applicationName = (String) (ai != null ? pm.getApplicationLabel(ai) : "(unknown)");
// Shortcut intent
Intent shortcutIntent = new Intent (Intent.ACTION_MAIN);
/** Problem in here **
shortcutIntent.setClassName(newAppContext, newAppContext.getClass().getName());
*********************/
shortcutIntent.addCategory(Intent.CATEGORY_LAUNCHER);
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// Create intent
final Intent putShortCutIntent = new Intent();
putShortCutIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
putShortCutIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, applicationName);
putShortCutIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
Intent.ShortcutIconResource.fromContext(newAppContext,
R.drawable.icon));
putShortCutIntent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
// Broadcast intent
context.sendBroadcast(putShortCutIntent);
}
EDIT:
Managed to achieve this by getting the Intent from PackageManager.getLaunchIntentForPackage(String packageName).
So:
// Intent shortcutIntent = new Intent (Intent.ACTION_MAIN);
// shortcutIntent.setClassName(newAppContext, newAppContext.getClass().getName());
// shortcutIntent.addCategory(Intent.CATEGORY_LAUNCHER);
// shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Intent shorcutIntent = pm.getLaunchIntentForPackage(appName);

You will get "wrong activity class name", when it cannot find the main activity class in the package. It needs that info so that it can launch the correct Activity in the correct package. So in your example, it should be:
shortcutIntent.setClassName("com.android.calculator2", "ClassName");
I don't know what the "ClassName" should be for the Calculator application(maybe you can check its source code), but it should be something like "com.android.calculator2.MainActivity"
EDIT:
Ok, it seems it is possible to get the "ClassName" dynamically:
PackageManager packageManager = context.getPackageManager();
ResolveInfo info = packageManager.resolveActivity(shortcutIntent, 0);
if(info != null) {
shortcutIntent.setClassName(info.activityInfo.packageName, info.activityInfo.name);
}

Related

Instagram application does not open with Android Intent

This is my code, the thing is I don't want to send images I just want the IG app to open. Yes the app is installed but still it is not getting picked up.
This was working fine till last week. Please help.
Uri uri = Uri.parse("http://instagram.com/");
Intent insta = new Intent(Intent.ACTION_VIEW, uri);
insta.setPackage("com.instagram.android");
if (isIntentAvailable(insta)) {
this.startActivityForResult(insta, REQUEST_CODE_MY_PICK);
} else {
}
private boolean isIntentAvailable(Intent intent) {
final PackageManager packageManager = getPackageManager();
List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
}
Try this
Uri appUri = Uri.parse("https://instagram.com/_u/user_name");
Uri browserUri = Uri.parse("https://instagram.com/user_name");
try{ //first try to open in instagram app
Intent appIntent = getPackageManager().getLaunchIntentForPackage("com.instagram.android");
if(appIntent != null){
appIntent.setAction(Intent.ACTION_VIEW)
appIntent.setData(appUri);
startActivity(appIntent);
}
}catch(Exception e){ //or else open in browser
Intent browserIntent = new Intent(Intent.ACTION_VIEW, browserUri);
startActivity(browserIntent);
}
Try to replace Uri.parse("http://instagram.com/") with Uri.parse("https://instagram.com/"). Also try to remove the isIntentAvailable and just call startActivity(insta) without 'forResult' and lastly remove insta.setPackage line.

Launch Telegram app from Android application with message and recipient

I need to open Telegram from my own Android App prepopulating both the message and recipient (and not having to choose betwenn Chrome or Telegram),
I achieved the first one with this code:
final String appName = "org.telegram.messenger";
Intent tIntent = new Intent(Intent.ACTION_SEND);
tIntent.setType("text/plain");
tIntent.setPackage(appName);
tIntent.putExtra(Intent.EXTRA_TEXT, msg);
mUIActivity.startActivity(tIntent);
And the second one with this code:
Intent tIntent = new Intent(Intent.ACTION_VIEW);
tIntent.setData(Uri.parse("http://telegram.me/USERID"));
startActivity(tIntent);
(I removed all checks like isTelegramInstalled for simplicity)
I tried to mix the two methods
adding some intent extra such as msg we get to this code that will open Telegram, in one click, with pre-populated message and recipient:
Intent telegramIntent = new Intent(Intent.ACTION_SEND);
tIntent.setDataAndType(Uri.parse("http://telegram.me/username"), "text/plain");
final String appName = "org.telegram.messenger";
tIntent.setPackage(appName);
tIntent.putExtra(Intent.EXTRA_TEXT, "hello");
startActivity(tIntent);
...aaand it didn't work!
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.SEND dat=http://telegram.me/... flg=0x1 pkg=org.telegram.messenger clip={null T:hello} (has extras) }
Any idea how to achieve this?
Please try below function for open Telegram
public static void openTelegram(Activity activity, String userName) {
Intent general = new Intent(Intent.ACTION_VIEW, Uri.parse("https://t.com/" + userName));
HashSet<String> generalResolvers = new HashSet<>();
List<ResolveInfo> generalResolveInfo = activity.getPackageManager().queryIntentActivities(general, 0);
for (ResolveInfo info : generalResolveInfo) {
if (info.activityInfo.packageName != null) {
generalResolvers.add(info.activityInfo.packageName);
}
}
Intent telegram = new Intent(Intent.ACTION_VIEW, Uri.parse("https://t.me/" + userName));
int goodResolver = 0;
// gets the list of intents that can be loaded.
List<ResolveInfo> resInfo = activity.getPackageManager().queryIntentActivities(telegram, 0);
if (!resInfo.isEmpty()) {
for (ResolveInfo info : resInfo) {
if (info.activityInfo.packageName != null && !generalResolvers.contains(info.activityInfo.packageName)) {
goodResolver++;
telegram.setPackage(info.activityInfo.packageName);
}
}
}
//TODO: if there are several good resolvers create custom chooser
if (goodResolver != 1) {
telegram.setPackage(null);
}
if (telegram.resolveActivity(activity.getPackageManager()) != null) {
activity.startActivity(telegram);
}
}
I hope this can help You!
Thank You.
In your case
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.SEND dat=http://telegram.me/... flg=0x1 pkg=org.telegram.messenger clip={null T:hello} (has extras) }
Telegram chat activity class has a different name and you pass other activity name.
Find which class use telegram for chat activity and pass it on set package method

API 23 (Android 6.0.1) InApp Billing: Service Intent must be explicit: Intent

I have been looking around and this seems to be a Android L related bug that was apparently solved solved using the code I already have.
When I try to call bindService I get:
Fatal Exception: java.lang.RuntimeException: Unable to resume activity
{MyActivity}: java.lang.IllegalArgumentException: Service Intent must
be explicit: Intent {
act=com.android.vending.billing.InAppBillingService.BINL }
This is the piece of code that causes the crash:
final Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
serviceIntent.setPackage("com.android.vending");
activity.bindService(serviceIntent, this, Context.BIND_AUTO_CREATE);
It only happens on Android 6.0.1 and my target in gradle in 23 and I can't seem to understand what's wrong with that on API 23...
If you are using IabHelper classes. Go to startSetup Method in IabHelper.java. add below code
Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
if (!mContext.getPackageManager().queryIntentServices(serviceIntent, 0).isEmpty()) {
// service available to handle that Intent
serviceIntent.setPackage("com.android.vending");
mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
}
else {
// no service available to handle that Intent
if (listener != null) {
listener.onIabSetupFinished(
new IabResult(BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE,
"Billing service unavailable on device."));
}
}
This method will help you turn the implicit intent into the explicit form. Inspired from SO answer: https://stackoverflow.com/a/26318757/1446466
bindServiceConn() method is creating a service.
* #param context
* #param implicitIntent - The original implicit intent
* #return Explicit Intent created from the implicit original intent
*/
public static Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) {
// Retrieve all services that can match the given intent
PackageManager pm = context.getPackageManager();
List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);
// Make sure only one match was found
if (resolveInfo == null || resolveInfo.size() != 1) {
return null;
}
// Get component info and create ComponentName
ResolveInfo serviceInfo = resolveInfo.get(0);
String packageName = serviceInfo.serviceInfo.packageName;
String className = serviceInfo.serviceInfo.name;
ComponentName component = new ComponentName(packageName, className);
// Create a new intent. Use the old one for extras and such reuse
Intent explicitIntent = new Intent(implicitIntent);
// Set the component to be explicit
explicitIntent.setComponent(component);
return explicitIntent;
}
protected void bindServiceConn() {
//call this method
Intent intent = createExplicitFromImplicitIntent(context.getApplicationContext(), new Intent("com.android.vending.billing.InAppBillingService.BIND"));
context.bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);
}
protected void unbindServiceConn() {
context.unbindService(mServiceConn);
context=null;
}

shortcut not opening app on android homescreen

I have installed a few apps on my android device, and I developed a code to create a shortcut for them, they all work apart from one app, but if I manually drag the app on homescreen it works, I'm really confused... the next code is what I used to create the shortcuts
try
{
//Log.i("shortcut method in androidhelper start","in the shortcutapp on create method ");
boolean flag =false ;
int app_id=-1;
PackageManager p = getPackageManager();
Intent i = new Intent(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> res =p.queryIntentActivities( i,0);
//System.out.println("the res size is: "+res.size());
for(int k=0;k<res.size();k++)
{
//Log.i("","the application name is: "+res.get(k).activityInfo.loadLabel(p));
if(res.get(k).activityInfo.loadLabel(p).toString().equals("Kortext")){
flag = true;
app_id = k;
break;
}
}
if(flag)
{
ActivityInfo ai = res.get(app_id).activityInfo;
Intent shortcutIntent = new Intent();
shortcutIntent.setClassName(ai.packageName, ai.name);
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
shortcutIntent.addCategory(Intent.ACTION_PICK_ACTIVITY);
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
// Sets the custom shortcut's title
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Kortext");
BitmapDrawable bd=(BitmapDrawable)(res.get(app_id).activityInfo.loadIcon(p).getCurrent());
Bitmap newbit;
newbit=bd.getBitmap();
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, newbit);
intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
sendBroadcast(intent);
}
else
{
// throw new UserException(UserException.KErrGeneral,"Application not found");
}
}
catch(ActivityNotFoundException e)
{
e.printStackTrace();
//throw new UserException(UserException.KErrGsmRRNoActivityOnRadioPath,e.getMessage());
}
catch(Exception e)
{
e.printStackTrace();
//throw new UserException(UserException.KErrGeneral,e.getMessage());
}
Any ideas?
I figured it out, I also had to change the intents to new Intent(Intent.ACTION_MAIN);

how to start another application from my application in android

final List<PackageInfo> packs = getPackageManager().getInstalledPackages(0);
The above PackageInfo class for get the list of packages then
get package names for :
ViewHendler hendler = new ViewHendler();
hendler.textLable = (TextView)convertView.findViewById(R.id.textView);
Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage(packageName);
startActivity( LaunchIntent );
then start applicathin using package name call :launchApp(packageName)
void launchApp(String packageName) {
Intent mIntent = getPackageManager().getLaunchIntentForPackage(packageName);
if (mIntent != null) {
try {
startActivity(mIntent);
} catch (ActivityNotFoundException err) {
Toast t = Toast.makeText(getApplicationContext(),
R.string.app_not_found, Toast.LENGTH_SHORT);
t.show();
}
}
}
But didn't get result(start another application from my application).
It's right way to use:
Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage("com.package.name");
startActivity(LaunchIntent);
But probably you have no permission, or you don't have application there.
Firstly check your packageName parameter.

Categories