The web and stackoverflow contain several examples how to get a file from another Android app (e.g., to use it as email attachment) using an ACTION_GET_CONTENT intent. But what kind of class do I have to implement to create an application providing content for the ACTION_GET_CONTENT event such as I can choose this app (e.g., for selecting an email attachment).
Is a ContentProvider the right solution? And what do I have to add to my AndroidManifest.xml?
After some hours of web search I found the following solution.
Implement an Activity handling intents. Within, use the following or more specific code:
Uri resultUri = // the thing to return
Intent result = new Intent();
result.setData(resultUri);
setResult(Activity.RESULT_OK, result);
finish();
Add the following to the Manifest:
<activity
android:name="ActivityName"
android:label="Some label" >
<intent-filter>
<action android:name="android.intent.action.GET_CONTENT" />
<category android:name="android.intent.category.OPENABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PICK" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>
starting from api level 18 incoming intent can also have EXTRA_ALLOW_MULTIPLE set to true and in this case you can send back in result more than one file. To do so you need to set it as ClipData:
resultIntent.setClipData(clipData)
Related
In my android application, I have registered for intent filter android.intent.action.SEND in one of my activities to receive data from other applications.
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
<data android:mimeType="application/pdf" />
<data android:mimeType="text/x-vcard" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
<data android:mimeType="application/pdf" />
</intent-filter>
When data is shared from other apps with my app using share intent, this activity receives the intent. I would like to know the package name of app which shared the data with my app.
I tried following code but it always returns null.
final String packageName = this.getCallingPackage()
Is there any way I can get the package name of app that shared data with my app using intent that i am receiving?
If the share intent was created using ShareCompat.IntentBuilder it will contain the extra EXTRA_CALLING_PACKAGE.
But most apps don't provide this information. And if the extra is present you should not use it for any security-critical functionality because senders are free to provide any value they like.
To use getCallingPackage(), the caller should use startActivityForResult(Intent, int) instead of startActivity(). Otherwise, it will return null. Straight from the doc:
Note: if the calling activity is not expecting a result (that is it
did not use the startActivityForResult(Intent, int) form that includes
a request code), then the calling package will be null.
https://developer.android.com/reference/android/app/Activity.html#getCallingPackage%28%29
In my android application, I have an intent filter linked to one of my activities in my AndroidManifest.xml like so:
<activity
android:name=".MainActivity"
android:label="#string/name >
<intent-filter>
<action android:name="android.intent.action.SEND />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
By my understanding this should add my app the list of apps in my browser (Chrome) that are under the "Share..." section so that my app can use the URL of the current web page. This list contains Flipboard, Android Beam, Twitter, Keep, Google+, etcetera.
I've found many examples on how to do this, they all use the above code. However, my app doesn't show up on that list for some reason. What could be the reason for this and how can I solve this issue?
Thanks!
You are including the action and category correctly but you also need to include the mimeTypes so that the Intent knows what type of sharing you want to support. Try including these two lines in order to support both text and image sharing:
<data android:mimeType="text/plain" />
<data android:mimeType="image/*" />
Like so:
<intent-filter>
<action android:name="android.intent.action.SEND />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
<data android:mimeType="image/*" />
</intent-filter>
If you then want to retrieve the URL from the Intent to utilise in your app then you'll want to add this code to your onCreate() method in MainActivity:
String action = intent.getAction();
if (action.equalsIgnoreCase(Intent.ACTION_SEND) && intent.hasExtra(Intent.EXTRA_TEXT)) {
String URL = intent.getStringExtra(Intent.EXTRA_TEXT);
}
Although I have gone through related document on google for app indexing
https://developers.google.com/app-indexing/webmasters/details
But still have confusion that If I want to receive incoming data on launcher activity and from there If can take control and start relevant activity/fragment depending on some internal parsing over incoming url.
You have to declare the action, category and data in a separate <intent-filter> tag, not in the same one with launcher specs.
<activity>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="your.domain.com"
android:scheme="http" />
</intent-filter>
</activity>
Not quite sure if I understood what your asking, so please correct me if I'm not answering your question.
Only the activity (or activities) that you put the intent filter in will catch an intent and start. Therefore, if you only put the intent filter in one activity, only that activity will start, and not any of the others. You can put multiple intent filters in the same activity to catch multiple intents. You can also use the path segment of the url to send more information to your activity, and parse it in your activity.
Put the following in your manifest under the activity you want to launch (the path is optional):
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http" android:host="www.yourwebsite.com" />
</intent-filter>
Use a url like http://www.yourwebsite.com/yourstring to open the app.
Then use getIntent().getData() to get the uri that started the activity. You can then parse the uri to get yourstring.
Add Following Intent filter to Activity you want to open via Deep linking in Manifest.
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
Then As per Intent data you get in Activity you can perform your action, too.
I'm writing an Android app that accompanies a website and I wanted to make the app intercept certain URLs. I found multiple examples through Google and on SO but none of them work. I create my Intent:
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://xgn.nl/article/" + String.valueOf(id)));
and then launch it from another Activity (where i is the intent from above)
startActivity(i);
The intent filter for the activity that should receive this is:
<activity android:name=".ArticleActivity" android:theme="#style/XGN.Red">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="http" android:host="xgn.nl" android:pathPrefix="/article/" android:mimeType="text/*" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
I also tried it without the mimeType in the filter. The intent resolver sees the filter but complains that the data does not match with the data in the intent and launches the browser instead.
What am I doing wrong?
I actually solved it 5s after I posted it, the problem was that you need to specify the fully qualified class name for this to work :)
<activity android:name="nl.xgn.ArticleActivity" android:theme="#style/XGN.Red">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="http" android:host="xgn.nl" android:pathPrefix="/article/" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
EDIT: To be more precise, the error I was seeing in logcat was wrong. The data type did match, but it chose the more visible browser class over my lazily defined activity. Specifying the full class name and removing the mimeType made this work.
Trying to launch and pass tel. no. to skype by this code from my app:
PackageManager packageManager = getPackageManager();
Intent skype = packageManager.getLaunchIntentForPackage("com.skype.raider");
skype.setData(Uri.parse("tel:65465446"));
startActivity(skype);
Skype is launched but it can't catch the number.
This code works for me to start a call between two Skype users:
Intent sky = new Intent("android.intent.action.VIEW");
sky.setData(Uri.parse("skype:" + user_name));
startActivity(sky);
To find this (and others), use apktool to open up the Skype APK. Look at the AndroidManifest.xml and you'll see all the intent filters they know about. If you want to trigger one of those intent filters, you need to make an intent that will match one. Here's the intent filter that the code above is matching:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="skype" />
</intent-filter>
You get the category "android.intent.category.DEFAULT" for free from new Intent(), so all that remains is to set the action and the URI.
The intent filter for tel: URIs looks like this:
<intent-filter android:icon="#drawable/skype_blue" android:priority="0">
<action android:name="android.intent.action.CALL_PRIVILEGED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="tel" />
</intent-filter>
So you set to the action and give the Intent a tel: URI and "the right thing happens". What happens is that Android finds the correct provider for the tel: URI. It might get the user's input to choose between the Phone App and Skype. The priority for Skype to handle tel: URIs zero, which is lowest. So if the Phone App is installed, it will probably get the Intent.
In case you want to trigger a video call you will have to add "?call&video=true" to your Skype URI.
Intent skypeVideo = new Intent("android.intent.action.VIEW");
skypeVideo.setData(Uri.parse("skype:" + "<username>" + "?call&video=true"));
startActivity(skypeVideo);
More information about Skype URIs are documented at:
http://developer.skype.com/skype-uris-program/skype-uri-ref
EDIT :
Direct Skype call without any intent chooser :
If you want direct skype call without any intent chooser, add these lines in your manifest file...
<intent-filter
android:icon="#drawable/skype"
android:priority="0" >
<action android:name="android.intent.action.CALL_PRIVILEGED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="tel" />
</intent-filter>
<intent-filter>
<intent-filter
android:icon="#drawable/skype"
android:priority="0" >
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.CALL" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="skype" />
</intent-filter>
</intent-filter>
Use this code for Skype version 2:
Intent skype_intent = new Intent("android.intent.action.VIEW");
skype_intent.setClassName("com.skype.raider", "com.skype.raider.Main");
skype_intent.setData(Uri.parse("skype:skypeusername"));
startActivity(skype_intent);
With this code you will get the intent of the Skype activity not the caller activity. So you have to find the intent for the activity which has the intent filter for action CALL. But more clearly Skype uses the action android.intent.action.CALL_PRIVILEGED, so find by this filter.
Just for information that caller activity is cmp=com.skype.raider.contactsync.ContactSkypeOutCallStartActivity.
Skype 2.X has significantly different manifest then Skype 1.X. There is no ContactSkypeOutCallStartActivity there. New manifest contains code:
<activity android:name="com.skype.raider.Main" android:launchMode="singleTask" android:configChanges="keyboardHidden|orientation" android:windowSoftInputMode="adjustResize">
...
<intent-filter android:icon="#drawable/skype_blue" android:priority="0">
<action android:name="android.intent.action.CALL_PRIVILEGED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="tel" />
</intent-filter>
...
</activity>
So you should write:
Intent skype_intent = new Intent("android.intent.action.CALL_PRIVILEGED");
skype_intent.setClassName("com.skype.raider", "com.skype.raider.Main");
skype_intent.setData(Uri.parse("tel:65465446"));
context.startActivity(skype_intent);
Please note, that this method doesn't allow you to start call/chat using Skype. It works with Skype Out only.
I found that the code above did not work...
Intent i = packageManager.getLaunchIntentForPackage("com.skype.raider");
// i.setAction("android.intent.cation.CALL_PRIVILEGED");
// i.setClassName("com.skype.raider", "com.skype.raider.contactsync.ContactSkypeOutCallStartActivity");
// i.setData(Uri.parse("tel:5551234"));
startActivity(i);
The commented out lines either stopped it functioning, or did nothing!
The code as presented will call Skype and arrive at a page where you can choose Skype contacts
More information will be most welcome
John