I created a music player and now I would like to implement a functionality that if I click a file (for example in Total Commander) it will open in my application. It already works on desktop but now I would like to also implement this feature in Android.
I know it must have been asked before but I couldn't find the answer.
I already found out that I need to define an intent-filter in AndroidManifest.xml:
<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="audio/*"/>
</intent-filter>
I did it and now my application opens (or I can choose it) if I click a music file. But now I need to do something in the java part (I do believe in the main activity onCreate function) too. How do I handle this?
Thank you.
The intent filter you specified, is already a step into the right direction.
Now other (Explorer-like-) Applications can start your app.
As a next step, you need to receive the data in the activities onCreate(...) function. This can be done like that:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
// Get the intent that started this activity
Intent intent = getIntent();
Uri data = intent.getData();
// Figure out what to do based on the intent type
if (intent.getType().equals("audio")) {
// Handle intents with audio ...
String filePath = data.toString();
// Do some handling here !
}
}
First you need to capture the Intent, that other apps use, to call your app. The intent contains the path of your file (as URI) structure. The only thing you need to do then is to get the URI String and get the path of your music file out of it.
Information about the intent filtering can be read here:
https://developer.android.com/training/basics/intents/filters
Related
I have an application where I need to do different task on different launch types. How to detect that app has been launched by deeplink, when my app was in background.
Assuming you already have an activity ready with the required intents what you'll to do is check your activity's if(getIntent().getAction() != null) which means it was launched via a deep-link. Normal intents used for navigation will return null.
Now the issue is if your activity was already running in background and you wrote this code in onCreate(), and the deep-linked activity was set to android:launchMode="singleTask" or launched with a FLAG_ACTIVITY_SINGLE_TOP it won't trigger again.
For this you will have to override onNewIntent(Intent intent) method of your activity, this way you can know each time your activity is started from an intent.
Again, here you can check if(intent.getAction() != null) and intent.getData() to retrieve the data.
One thing to note is to avoid running the same code twice in onCreate and onNewIntent
In case you haven't implemented deep-linking in your app yet you will first need to make use of <intent-filter> to make an activity be available to handle the intent when clicking on a link etc. as an example
<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="www.example.com"
android:pathPattern="/.*"
android:scheme="https" />
</intent-filter>
You can read more about on the official Docs here as someone already suggested.
Inside any activity you have specified the intent filter, you can get the URL via the Intent that launched the activity.
Activity:-
Intent appLinkIntent = getIntent();
Uri appLinkData = appLinkIntent.getData();
Fragment:-
Intent appLinkIntent = requireActivity().getIntent();
Uri appLinkData = appLinkIntent.getData();
in MainActivity i use this code
if(getIntent().getDataString()!=null &&
getIntent().getDataString().contains("specialWordInDeepLink")){
// confirm is run by deeplink
}
When a clicked link or programmatic request invokes a web URI intent, the Android system tries each of the following actions, in sequential order, until the request succeeds:
Open the user's preferred app that can handle the URI, if one is designated.
Open the only available app that can handle the URI.
Allow the user to select an app from a dialog.
To create a link to your app content, add an intent filter that contains these elements and attribute values in your manifest:
https://developer.android.com/training/app-links/deep-linking
Check out official android doc to know more about deeplinking
My app can receive new files using "file open" intents:
<activity android:launchMode="singleTask" >
<intent-filter android:label="Text document" android:priority="1">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="content"/>
<data android:scheme="file"/>
<data android:host="*"/>
<data android:mimeType="*/*"/>
<data android:pathPattern=".*\\.txt"/>
</intent-filter>
</activity>
The actual data is processed in the onCreate or onNewIntent methods:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// process intent data using getIntent().getData();
// When the app is started from a file request then the intent contains the file data.
// Settings the intent to some dummy data after processing to prevent getting the same data
// when the task is brought back again from background does not work:
setIntent(new Intent());
}
When the task is already running then this is called:
#Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
// process intent data here using intent.getData();
}
All this works fine unless the app is restarted from the Android backgrounded task selection viewer ("recent list of apps"). Each time the app is started from the task selection viewer then the getIntent().getData() is reset to the initial data which causes my app to get the same file data again.
To be more specific these are the steps:
Launch the app by clicking on a *.txt file. onCreate gets the file info.
Press the "back" key to exit the app.
Show the Android task viewer and click on the screenshot of my app. onCreate gets the same file info again. How can this be prevent?
The problem does not occur here:
Launch the app by clicking on a *.txt file. onCreate gets the file info.
Press the "back" key to exit the app.
Now I click on my app's icon in the Android launcher. onCreate does not get the file info again. This is what I want.
Is there a way to clear the getIntent() object so that it is not reset each time my app is created?
Regards,
I found a working solution:
if (((getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY)) == 0) {
// process intent data
}
For example, there is an uri example://activityone?foo=bar which can open up an application and launch one of the activity by this adb command
adb shell am start -W -a android.intent.action.VIEW -d "example://activityone?foo=bar" com.example.deeplinking
Are there any other ways to launch the android app through this uri (example://activityone?foo=bar)? How can I put this uri in an email, and when it is clicked, it will launch the app?
First, you should read the documentation for this: Intents and Intent Filters. Specifically the section "Receiving an Implicit Intent".
As others have stated, using a custom scheme for this has issues.
They aren't always treated as links
You don't own them like you own a domain name (host).
So you should define an activity in you Manifest with an intent filter for your host and use a real scheme. See the "Action Test", "Category Test" and "Data Test" sections of the Intent & Intent Filters documentation to see how to configure this for your specific use case.
<activity android:name="com.example.app.ActivityOne">
<intent-filter>
<data android:scheme="http"/>
<data android:host="example.com"/>
<data android:path="/activityone"/>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
</activity>
Then you will be able to use a link like the following.
http://example.com/activityone?foo=bar
Since this is an http link the system will ask the user to choose which app to open it with (your app or their preferred browser). If they choose your app it will start ActivityOne which can get the query data like so.
public class ActivityOne extends Activity {
#Override
public void onResume() {
super.onResume();
Intent intent = getIntent();
Uri uri = intent.getData();
String foo = uri.getQueryParameter("foo");
}
}
If you use a custom scheme in the intent filter then you will (most likely) be the only app registered to handle that intent and the user will not have to select your app. However, it will be much harder for you to include a link with a custom scheme in an email. Most email clients will not recognize anything with a custom scheme as a link and it will not be clickable.
Non-standard URL schemes (which is what example:// is) aren't always treated as links. Your best option is to somehow wrap that URL inside a link that the app CAN recognize (http:// or https://), and then take care of opening your app later, usually by way of some sort of automatic redirect. This is how we handle things to make sure the app always launches no matter where the link is opened.
I'm making a music player app and I'd like it to have the option of becoming the default music app. I've been reviewing the documentation here but haven't had much luck understanding it.
http://developer.android.com/guide/components/intents-filters.html
I've gathered I need to use android.intent.category.DEFAULT but after that... I'm stuck.
My question is this: If someone selected an mp3 file, and my app was the default app and opened... Where / how do I select which Activity/Service and method to open the file with? And where wou7ld I get the file path for the file that the user selected?
If user clicks on .mp3 file you want to launch your application for playing that .mp3 file
You have to put a intent filter in your manifest file which will have this intent
android.intent.category.APP_MUSIC
Please read the Documentation for the same.
I figured it out :-)
AndroidManifest:
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="file" android:pathPattern=".*mp3" android:mimeType="audio/mpeg" />
</intent-filter>
MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState)
{
if (Intent.ACTION_VIEW.equals(getIntent().getAction()))
{
File file = new File(getIntent().getData().getPath());
// do what you want with the file...
}
I'm trying to pass data to my activity, but unfortunately I'm still unsuccessful. What I am trying to accomplish is to select a file in the file browser, share it and pass the data to my activity.
Inside my manifest I added an intent filter:
<activity android:name=".MyActivity" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="*/*"/>
</intent-filter>
</activity>
Inside my Java file i'm trying to get the data:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.myactivity);
Intent intent = getIntent();
Uri data = intent.getData();
if (data != null) {
// process the data
} else {
// no data received
}
}
When I select a file from My Files and share it, my app is visible in the list, when i click it it launches my activity, but intent.getData(); always returns null.
Am i missing something? Thanks.
you can get the data from the example given below:
Use an with a element. For example, to handle all links to twitter.com, you'd put this inside your in your AndroidManifest.xml:
<intent-filter>
<data android:scheme="http" android:host="twitter.com"/>
<action android:name="android.intent.action.VIEW" />
</intent-filter>
Then, when the user clicks on a link to twitter in the browser, they will be asked what application to use in order to complete the action: the browser or your application.
Of course, if you want to provide tight integration between your website and your app, you can define your own scheme:
<intent-filter>
<data android:scheme="my.special.scheme" />
<action android:name="android.intent.action.VIEW" />
</intent-filter>
Then, in your web app you can put links like:
<a href="my.special.scheme://other/parameters/here">
And when the user clicks it, your app will be launched automatically (because it will probably be the only one that can handle my.special.scheme:// type of uris). The only downside to this is that if the user doesn't have the app installed, they'll get a nasty error. And I'm not sure there's any way to check.
Edit: To answer your question, you can use getIntent().getData() which returns a Uri object. You can then use Uri.* methods to extract the data you need. For example, let's say the user clicked on a link to http://twitter.com/status/1234:
strong textUri data = getIntent().getData();
String scheme = data.getScheme(); // "http"
String host = data.getHost(); // "twitter.com"
List<String> params = data.getPathSegments();
String first = params.get(0); // "status"
String second = params.get(1); // "1234"
You can do the above anywhere in your Activity, but you're probably going to want to do it in onCreate(). You can also use params.size() to get the number of path segments ienter code heren the Uri. Look to javadoc or the android developer website for other Uri methods you can use to extract specific parts.
Launch custom android application from android browser