I am attempting to get one activity to launh another via an intent and intent filter. Here is what I have.
In the launching activity:
Intent i = new Intent();
i.setAction("com.test.apps.CATAPP");
i.addCategory("com.test.apps");
this.startActivityForResult(i,APP_REQUEST_CODE);
The intent filter in the receiving app:
<intent-filter>
<action android:name="com.test.apps.CATAPP" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.test.apps" />
<data android:mimeType="text/plain"/>
</intent-filter>
This fails to work. However, if I take the example from Wei Meng Lee's Android 4 Development, it works and then only if the URI and the Intent.ACTION_VIEW are present.
Code in the launching app:
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("http://google.com"));
i.setAction("com.test.apps.CATAPP");
i.addCategory("com.test.apps");
this.startActivityForResult(i,APP_REQUEST_CODE);
Intend in the receiving app:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="com.test.apps.CATAPP" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.test.apps" />
<data android:scheme="http"/>
</intent-filter>
Where am I going wrong? Have I made a simple mistake?
I have spend the last couple of hours trawling stack overflow, for anwer to this but only found similar questions, with answers that did not solve my problem or were not applicable.
In your first example, your Intent is not going to match the IntentFilter of the Activity. You've specified a data element in the IntentFilter, but you've not set one on the Intent. You can either set the MIME type on the Intent:
i.setType("text/plain");
Or remove the <data> element from the <intent-filter> in the manifest, depending on your requirements.
If you just want to pass some simple text, set the Intent's type as shown above, and attach a String extra to it.
i.putExtra(Intent.EXTRA_TEXT, "Plain text.");
Then, to retrieve the text in the next Activity:
String plainText = getIntent().getStringExtra(Intent.EXTRA_TEXT);
if(plainText != null)
...
Note that the Intent.EXTRA_TEXT constant is merely a convenience. The extra key can be anything you want, as long as it's the same in both places.
Related
I have an app where the user should be able to share some text. Now I want to provide the default sharing options for plain text that Android provides. I do so with the following code:
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, text);
sendIntent.setType("text/plain");
Intent chooser = Intent.createChooser(sendIntent, "Share");
startActivity(chooser);
This will look a bit like that:
Source: http://developer.android.com/training/basics/intents/sending.html
But now I also would like to be able to have one more option in the Share-Service-Picker Dialog that triggers a custom action in my own code. Namely I want the user to be able to favourite an entry. So beside sharing via SMS, Email, FB, whatever, I'd like there to be one more item on the top of that list, saying "Add to favourites" (Including an icon if possible).
So my question is if that's possible?!? And if, how :)
Any tips are appreciated!
Intent filters inform the system what intents an application component is willing to accept. Similar to how you constructed an intent with action ACTION_SEND in the Sending Simple Data to Other Apps lesson, you create intent filters in order to be able to receive intents with this action. You define an intent filter in your manifest, using the element. For example, if your application handles receiving text content, a single image of any type, or multiple images of any type, your manifest would look like:
<activity android:name=".ui.MyActivity" >
<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" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity>
from Receiving Simple Data from Other Apps:Update Your Manifest
I am trying to read (first time - new to me) a gmail attachment (.gcsb extension) in my app. The intent filter looks like this:
<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:pathPattern="*.gcsb"></data>
<data android:mimeType="application/*"></data>
</intent-filter>
and that appears to get the 'download' and 'preview' buttons to appear next to the attachment in gmail (without that filter, the buttons do not appear).
In the activity (onCreate() / onRestart()) I do:
....
Intent intent = getIntent();
if (!Intent.ACTION_VIEW.equals(intent.getAction())) {
// Deal with the file from gmail here
}
....
to check if it is gmail that has caused this to start the activity or not.
However intent.getAction() always resolves to android.intent.action.MAIN, so it never does anything. There is another intent filter in the activity:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
being for the app launch, but I don't understand why I never see the android.intent.action.VIEW from gmail?
The answer appears to be that the activity was set to be 'single instance' for various reasons. This means that whilst it is brought to the foreground again, it comes back with the intent it was originally started with, not the one created by gmail.
Removing the 'single instance' attribute allowed the correct intent to be used.
That is, in addition to select-copy-paste, I need your own item. Not only in my application, but also in others.
Is it real?
Yes it is real take a look at http://developer.android.com/guide/topics/clipboard/copy-paste.html
This is provided by Android 6 and above if your app implements the PROCESS_TEXT intent filter. For example in your AndroidManifest.xml:
<activity android:name="My Romanizer App"
android:label="Romanize this text">
<intent-filter>
<action android:name="android.intent.action.PROCESS_TEXT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
Then in your onCreate() method, check getIntent().getCharSequenceExtra(Intent.EXTRA_PROCESS_TEXT).toString()
If you want to return replacement text to the app that called you, you'll need to do something like:
Intent i=new Intent();
i.putExtra(Intent.EXTRA_PROCESS_TEXT, "you have been romanized");
setResult(RESULT_OK, i);
and you can detect if sending back a result is appropriate by checking if getIntent().getBooleanExtra(Intent.EXTRA_PROCESS_TEXT_READONLY, false)==false.
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
What I want: To be able to send my custom file by mail and import it with my application from the preview button in GMail or when opening it in a file browser.
What I know: I've read a lot of custom mime type handlers, that android doesn't care about file extension etc., but how to create the mime type for my custom file?
The question: Do I need to be a content provider? I just want to import files (from backup) not provide anything. I've seen people having handlers for "application/abc" saying it's working fine, but how to add that connection for my file "myFile.abc" and the mime type?
Some direction how to register/map custom mime types would be appreciated! :)
As far as I can tell, mime types are pretty flexible (I created mine as application/whatever) and they're accepted immediately by Android, as far back as Dalvik version 2.1. To handle them properly, I added this intent-filter:
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="application/whatever" />
</intent-filter>
There is a caveat though. Even though I always set the type of the send Intent with intent.setType("application/whatever");, on some phones I've seen the actual data on arrival as application/octet (to see the value, I assigned the incoming Intent and inspected its value directly Intent currentIntent = getIntent();). The receiving Android device didn't know what to do with the incoming data and told me so. So I added
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="application/octet-stream" />
</intent-filter>
This approach could be troublesome of course, but the problem with Gmail at least is that it doesn't necessarily write the file with the name as it comes in, which renders any Path I choose to define useless. And at least with an incoming octet-stream you know it's not any app's specific data you're stealing away... Still, you should validate the data afterwards and not just assume it's valid for your app.
I have added custom mime type in android contacts list. After a long research i decided to share this with you guys, i have tested this on all Android cell phone including android 9.0.
here is my Github link
Untested, but something like this should work. Put it in your AndroidManifest.xml with the activity you want to open the file:
<activity name=".ActivityHere">
<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="file" />
<data android:mimeType="mimeTypeHere" />
</intent-filter>
</activity>
<activity
android:name="MainActivity"
android:label="#string/app_name"
android:theme="#android:style/Theme.NoTitleBar.Fullscreen" >
<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 mime}.com"
android:scheme="http" >
</data>
</intent-filter>
</activity>
<!--
android:scheme="http" will make android "think" thats this is a link
-->
Now, when you receiving a sms with the text "http://{your mime}.com" or clicking link on the web with this text, your activity (MainActivity) will run.
You also can add parameters:
text = "http://{your mime}.com/?number=111";
Then in onCreate() or onResume() methods you'll add:
Intent intentURI = getIntent();
Uri uri = null;
String receivedNum = "";
Log.d("TAG", "intent= "+intentURI);
if (Intent.ACTION_VIEW.equals(intentURI.getAction())) {
if (intentURI!=null){
uri = intentURI.getData();
Log.d("TAG", "uri= "+uri);
}
if (uri!=null)
receivedNum = uri.getQueryParameter("number");
}
Register a custom mime type using android.webkit.MimeTypeMap