In my application I have an option to start navigation to selected POI. Basically what I want is to launch a turn-by-turn navigator from my application. The thing is I don't know which (if any) navigator is installed.
So, the question is how to start an intent by showing a list of suitable activities for navigation to the user first, letting him choose which one he would like to use? Also would be nice to find a way to pass extra parameters to selected activity (this sounds like an issue to me, since different navigation apps use different names for their extras, I guess).
In case it's not clear: I'm looking for a way to DISPLAY A LIST OF SUITABLE APPLICATIONS FOR NAVIGATION WITH THE OPTION TO MAKE ONE DEFAULT.
EDIT: Find here the implementation http://datamoil.blogspot.com/2011/04/android-universal-intent-to-start.html
The bad news is, there isn't a standard Intent URI for navigation.
Yes, google.navigation URIs exist, and an app may choose to support it.
The best solution I can think of is to:
Explicitly check for known apps
Implicitly check for apps hooking google.navigation: and perhaps geo: (but then you also get map apps)
You can enumerate the possible implicit targets using PackageManage.queryIntentActivities
Try:
Intent intent = new Intent(Intent.ACTION_VIEW,
Uri.parse("google.navigation:q=New+York+NY"));
startActivity(intent);
First I used in my onTap method inside the button's listener:
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("google.navigation:q=New+York+NY"));
mContext.startActivity(i);
Then in manifest simply use:
<activity android:name=".LaunchGPS" android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
This will open any Navigator App your phone has such as VZ Navigagtor, Google or whatever the phone is loaded with. Worked for me the first time perfectly. Hope this solves your problem.
I found more advantages using this code (just for to show available navigator apps)
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("geo:"));
if (intent.resolveActivity(getActivity().getPackageManager()) != null) {
startActivityForResult(Intent.createChooser(intent, "Continues with:", CHOOSE_NAVIGATOR_ID);
} else {
// Handle failure...
}
Related
I want to launch an activity from another application inside my own app. I have control over both applications.
For it, I'm using the explicit intent and it works well.
Intent intent = new Intent();
ComponentName componentName = new ComponentName("br.com.example.app","br.com.exemple.app.myactivity");
intent.setComponent(componentName);
My problem occurs when I click on the overview button, the new application appears inside the same item when overview screen (Recents Screen). Thus, the user can figure out if he is one the App1 or App2. Actually, he will think that he is still inside App1.
How do I force it to appear on a different item on the Overview Screen?
I already tried to use
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
and
<activity
android:name=".myactivity"
android:exported="true"
android:screenOrientation="portrait"
android:theme="#style/ApiBaseThemeNoActionBar"
android:documentLaunchMode="always">
</activity>
It seems to work well when using only startActivity(intent).
See the documentation for FLAG_ACTIVITY_NEW_TASK:
This flag can not be used when the caller is requesting a result from the activity being launched.
So in your case, I guess if you're asking for a result, android forces you to stay in the same task.
“My First App” has an activity that handles a “share” intent. Its activity in AndroidManifest.xml looks like this:
<activity
android:name="com.example.foo.myfirstapp.MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="image/jpeg"/>
</intent-filter>
</activity>
In KitKat, sharing an image from the album to “My First App” causes MainActivity to be part of the album’s task. This is the desired behavior.
In Lollipop, sharing an image from the album to “My First App” causes a new instance of “My First App” to be launched. If I look at the overview screen, the album task is there...and then there's a separate entry for "My First App". If I share another image, I wind up with two instances of "My First App"...etc.
Question: How do I make Lollipop process the share intent in the same way as KitKat?
Here's what I've done:
I notice that the intents sent from the Album have different flags set depending on the OS. (I got these using getIntent() and looking at mFlags.)
Kitkat: 0x80001 (524289): FLAG_GRANT_READ_URI_PERMISSION, FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
Lollipop: 0x18080001 (403177473): FLAG_GRANT_READ_URI_PERMISSION, FLAG_ACTIVITY_MULTIPLE_TASK, FLAG_ACTIVITY_NEW_DOCUMENT, FLAG_ACTIVITY_NEW_TASK
From reading http://developer.android.com/reference/android/content/Intent.html, it seems that these last three flags are causing the problem. Specifically
When paired with FLAG_ACTIVITY_MULTIPLE_TASK both of these behaviors (FLAG_ACTIVITY_NEW_DOCUMENT or FLAG_ACTIVITY_NEW_TASK) are modified to skip the search for a matching task and unconditionally start a new task.
I’ve been attempting to “override” these flags by specifying android:launchMode and android:documentLaunchMode in the activity in AndroidManifest.xml without success.
From http://developer.android.com/reference/android/R.attr.html#documentLaunchMode, using documentLaunchMode “never” seems promising, since
This activity will not be launched into a new document even if the Intent contains Intent.FLAG_ACTIVITY_NEW_DOCUMENT. This gives the activity writer ultimate control over how their activity is used.
but this didn't work.
I also considered android:taskAffinity, but there doesn’t seem to be a way to say “please prefer whatever task launched you”.
Afraid you can't do anything about this. It isn't under your control. This is a change in the way the "Album" app is launching its "share" Intent. If it doesn't want your Activity in its task, you can't force it in there.
If you have issues with having multiple instances of your "share" activity, you could declare your "share" activity as launchMode="singleTask" or launchMode="singleInstance" (depending on your needs. This may, however, break other things.
I am looking to start an activity in my app using a custom action. I have found a few answers but everything I try it throws java.lang.RuntimeException saying No Activity found to handle Intent { act=com.example.foo.bar.YOUR_ACTION }.
This is the activity in my manifest file:
<activity
android:name=".FeedbackActivity" >
<intent-filter>
<action android:name="com.example.foo.bar.YOUR_ACTION" />
</intent-filter>
</activity>
And this is how I'm starting the activity:
Intent intent = new Intent("com.example.foo.bar.YOUR_ACTION");
startActivity(intent);
Any help would be greatly appreciated.
I think what you need is to add a default category to your intent-filter,
eg.
<activity
android:name=".FeedbackActivity" >
<intent-filter>
<action android:name="com.example.foo.bar.YOUR_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
see this answer for more info.
I think you are creating your intent wrong. Try like this:
String CUSTOM_ACTION = "com.example.foo.bar.YOUR_ACTION";
//Intent i = new Intent(this, FeedBackActivity.class); // <--- You might need to do it this way.
Intent i = new Intent();
i.setAction(CUSTOM_ACTION);
startActivity(i);
Just add and intent-filter category as Default.
Implicit intent works perfectly and in many cases its better to use a implicit intent with Intent-action to call a service/Activity than using class-name.
Before startActivty() / startService() with proper context you cane use this method 'queryIntentActivities(Intent intent, int flags)' from package manager class.
It helps the ActivityManager (responsible for launching activities) to check whether the Android system is getting any match with you Intent.
If it doesn't it returns a list size 0 or else >0.
By this you can also check if your app is getting the call,and in this case even if your app is not installed / has got some problem, it will not crash but will throw a warning in Log. Users will face no big trouble apart from app not being launched.
(users will never forgive you if tour app crashes).
Hope this will help !!!
Happy Coding. :)
I faced the same problem when trying to launch the activity residing in the dynamic feature module and starting through action String as the Activity is not resolvable by name at compile time.
So I set the action but the activity crashes every time (No Activity found to handle intent bla bla.. ) until I set the correct package name.
Context c = getApplicationContext();// flag would be require Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag
Intent i = new Intent(action_string);
i.setPackage(context.getPackageName());//this did the trick actually
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
In the Manifest : add catrgory default to the intent filters
from google docs:
<category android:name="android.intent.category.DEFAULT"/>
Note: In order to receive implicit intents, you must include the CATEGORY_DEFAULT category in the intent filter. The methods startActivity() and startActivityForResult() treat all intents as if they declared the CATEGORY_DEFAULT category. If you do not declare it in your intent filter, no implicit intents will resolve to your activity.
guys. I am trying to build a voip app for android. I want to make use of the built-in android phone dialer. Can you guys give me some reference to it. I have been googling with no luck. Thanks
What you need to do is setup an Intent filter on the Activity you want to make the call. You do this inside your AndroidManifest.xml file. Modify your activity definition to include this intent filter:
<intent-filter>
<action android:name="android.intent.action.CALL" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="tel" />
</intent-filter>
Note: there are some alternative ways to call people (which can be seeing in the AndroidManifest.xml of the source I linked bellow, however this is the main one
Adding this will give the user the option to use your app when making a call, and this can be set as the default app if the user wishes.
You can then get the phone number by adding something like this code to your onCreate() method of your activity:
final Intent i = getIntent();
final Uri phoneUri = i.getData();
phoneUri now contains tel:00000000000 and you can easily get the number out of the Uri object
If you have problems in to future take a look at the android source. I got these bits of code from the phone app source if you want to take a look.
This should open the dialer with new special permissions:
Intent i = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:0000000000"));
startActivity(i);
That should open the dialer with the required telephone number already inserted.
I'm working on an activity which other 3rd parties want to use in their own apps, via intents.
Right now this activity is catching urls via an intent filter, like this:
<activity android:name=".MyActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW"></action>
<category android:name="android.intent.category.DEFAULT"></category>
<category android:name="android.intent.category.BROWSABLE"></category>
<data android:host="www.mysite.com" android:pathPrefix="/test/" android:scheme="http"></data>
</intent-filter>
</activity>
The above works, whenever a user clicks a link in my app like:
"mysite.com/test/blah.html"
my app comes up as a choice, along with the browser, to open the link.
Now if a third party wants to use my app, I think they can use the above like this:
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://mysite.com/test/somedata"));
startActivity(intent);
While this would work, this probably won't give them the desired effect of jumping directly to my activity from theirs - the android chooser dialog will appear, asking if they want to open the intent data with the browser, or my app.
How can I let 3rd parties call my activity directly without broadcasting the intent like this? I'd like to make them still pass the same exact data scheme to me, but just let them open my activity directly.
Thank you
You would most likely need for them to call your activity directly
Class yourClass = Class.forName("com.yourdomain.yourapp.YourClass");
Intent intent = new Intent(this, yourClass);
If they don't have a jar to link against. Otherwise, they could just use
Intent intent = new Intent(this, YourClass.class);
And then put some extras in there. The whole concept of the browsable intent (along with the others) is to provide users with a choice of how they would like to view/use something. This is similar to what happens when you click "share" from the media viewer. The whole concept is to give them choice. If somebody wants to just start your activity, they will need to explicitly call it.
Edit: My reflection example above won't directly work unless the Dalvik class loader knows about your class (which it probably won't). You will actually need to specifically tell the VM to load a class from a foreign package. You can do that with the following code
Context foreignContext = createPackageContext("com.yourdomain.yourapp", Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE);
Class<?> yourClass = foreignContext.getClassLoader().loadClass("com.yourdomain.yourapp.YourClass");
Now that they have the class object, they can then fire the intent like before. So the complete code is something like
Context foreignContext = createPackageContext("com.yourdomain.yourapp", Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE);
Class<?> yourClass = foreignContext.getClassLoader().loadClass("com.yourdomain.yourapp.YourClass");
Intent intent = new Intent(this, yourClass);
startActivity(intent);
The solution described above by Chris Thompson didn't work for me. This one did: Android: Starting An Activity For A Different Third Party App
Just in case anyone runs into the same problem as I did.