My app can save and load a custom type of files, let's say .foo.
My manifest tells this :
<activity
android:name=".activity.LoadActivity"
android:label="dummy">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file" />
<data android:host="*" />
<data android:pathPattern=".*\\.foo" />
</intent-filter>
</activity>
With this, I can launch my activity when a browser try to open a .foo file.
But in my activity, onCreate() is called, but not onActivityResult(), how can I get the path to the file that get clicked ?
I've been searching the doc for a long time, cannot figure this out.
how can I get the path to the file that get clicked?
You can simply retrieve it from the incoming Intent. Just call:
Intent intent = getIntent();
intent.getData().toString();
To answer your whole question:
But in my activity, onCreate() is called, but not onActivityResult(), why ?
You can find the answer directly from the method Javadoc:
Called when an activity you launched exits [...]
This is not your case. onActivityResult is called only on activities that you launched (from your code). In the scenario that you're describing your activity is called from another application (the browser).
onActivityResult will be called after the ending of an activity you launched with method startActivityForResult
How can I get the file that led to my activity then ?
Call getIntent() in onCreate() to get the Intent that was used to start your activity. On there, getData() will return the Uri pointing to the file.
Related
I have two Android applications.
The first application is the "browser". It gets an URL and displays it in a WebView. The corresponding activity is declared as:
<activity android:name=".MainActivity">
<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.BROWSABLE" />
<data android:scheme="http" />
<data android:scheme="https" />
</intent-filter>
</activity>
The second application has a few buttons. Tapping each button opens the first application and sends the URL to it using Intent.ACTION_VIEW:
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse(urlString);
intent.setData(uri);
intent.setComponent(new ComponentName("com.custom.browser", "com.custom.browser.MainActivity"));
startActivity(intent);
I expect this code to start a new activity as per https://developer.android.com/reference/android/app/Activity. So the browser application retrieves the URL in onCreate() by using the code:
#Override
protected void onCreate(Bundle savedInstanceState) {
...
Intent intent = getIntent();
if (intent != null && Intent.ACTION_VIEW.equals(intent.getAction())) {
displayUrl(intent.getDataString());
}
...
}
However I found that sometimes onCreate() is not called. After calling startActivity(intent), the browser application is just brought to the front, therefore displaying a previous URL.
I can override this behavior by moving the intent retrieval code in the onResume().
However I'd like to understand what am I doing wrong? Shouldn't the method startActivity(Intent) always start a new activity and always call onCreate(), as suggested by the Android documentation?
I expect this code to start a new activity
That is not necessarily what will happen.
However I found that sometimes onCreate() is not called. After calling startActivity(intent), the browser application is just brought to the front,
Yes, that will happen if the activity you are starting is already running at the front of a task. See the documentation for tasks.
I can override this behavior by moving the intent retrieval code in the onResume().
That will not work. Override onNewIntent() and get the new Intent there. Or, adjust the flags in your Intent, or adjust the manifest settings for the activity that you are starting, as is discussed in the documentation for tasks.
My app is supposed to handle shared texts. For example URLs from the amazon app. So I added the following intent-filter to my main activity:
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
In my onCreate function of my activity, I'm processing the intent like so:
intent = getIntent();
if(intent.getAction() != null) {
if (intent.getAction().equals(Intent.ACTION_SEND)) {
if (intent.getType().equals("text/plain")) {
onNavigationDrawerItemSelected(1);
}
}
}
The problem is, that sometimes the onCreate function isn't called following a sharing action.
I checked the onResume method, and indeed that's what is called. The problem is that the intents action isn't "ACTION_SEND", but is packagename.handled and doesn't contain the needed information.
Why is that?
If your activity already exists, depending on Intent flags and <activity> attributes, that existing activity instance may be reused. Override onNewIntent() to get the Intent being delivered to an existing activity instance that is causing it to be brought back to the foreground. Look in there for your ACTION_SEND values.
I have an app with only two activities, MainActivity and SecondActivity. MainActivity has an intent-filter in order to handle a particular set of URLs for deep-linking:
<activity android:name=".MainActivity">
...
<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="example.com" android:pathPrefix="/link" />
</intent-filter>
When an Intent with ACTION_VIEW and an uri is received, I want to redirect to SecondActivity depending on the full URL. Therefore, in both onCreate() and onNewIntent(), I call this method:
private void handleIntent(Intent intent) {
if (Intent.ACTION_VIEW.equalsIgnoreCase(intent.getAction()) && intent.getData() != null) {
if (intent.getData().toString().contains("/link/")) {
startActivity(new Intent(Intent.ACTION_VIEW, intent.getData(), this, SecondActivity.class));
}
}
}
I then test this code by adding a few links to an e-mail (such as http://example.com/link1/one and clicking on them. The problem I noticed is the following:
When I click on a link, MainActivity.onCreate() is correctly fired, and SecondActivity is called. If I then click the same (or another) link again, then all works well. However, if I go back from SecondActivity to MainActivity, then clicking on the same link does not execute my code -- the application is brought back to the front, and nothing else. Neither onCreate() nor onNewIntent() is called.
This would seem to be the correct behavior only if Android assumed that the Activity that declares the intent-filter is the one showing the content of the URI. However, in this case it's not, and I haven't found a way to work around it.
While this is a special case, a similar situation presents itself if the Activity shows a different Fragment depending on the URI. If I later replace that Fragment while staying in the same Activity, then clicking on the URL should redeliver the Intent so the original Fragment can be shown again -- but this does not happen.
Is there a way to receive this intent again? Due to the way the app is stuctured I cannot place the intent-filters on the child activities themselves (indeed, most times they are Fragments as mentioned above) nor declare any of these as singleTop (because they are reused elsewhere for other purposes).
FWIW, the full application code is available here.
I am trying to start an activity within my app from a custom uri returned from my service.
For example my service is going to return me something like: "activity2". Basically I want to start the activity that has the correct filter listening for the "activity2" intent. I am kind of stuck on how I would do this. Can anyone give me an example of some sort?
In my Activity2 declaration I put this as an intent filter but it doesnt seem to work:
<intent-filter>
<action android:name="activity2"/>
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="foo"/>
</intent-filter>
If I have a content provider and CONTENT_URI in in application A, and it is also in the manifest. How do I call to it from application B?
Do I need to write the code in class that holds my sqlite database? Or do I need to make a whole new class and call to the provider from there?
Thanx in advance.
You may register Activity B to accept URIs according to their nature.
To do so, you add the following "intent-filer" section to Activity B in the AndroidManifest.xml
<activity android:name="ACTIVITY B PATH">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="THE MIME TYPE TO ACCEPT" />
</intent-filter>
</activity>
This will register Activity B to accept VIEW actions with URIs that math the MIME type.
Then, when Activity A runs the following code:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(CONTENT_URI));
activity.startActivity(intent);
Activity B will be activated automatically and you can read the URI by calling getIntent().getData() from your onCreate() method.
You may choose different ACTIONS (VIEW, EDIT, INSERT...) and DATA TYPES (MIME, SCHEMA, PATH...) that is most suitable to your needs.