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
}
Related
I developed a deep link app.
The intent data remains, when I close the app by the back button and restart from the task After launching from deep link.
Manifest:
<application
<activity
android:name=".MainActivity"
android:label="#string/appName"
android:launchMode="singleTask">
<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="news"
android:scheme="example" />
</intent-filter>
</activity>
<activity
android:name=".NextActivity" />
</application>
MainActivity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (intent.action == Intent.ACTION_VIEW && Uri.parse(intent.data.toString()).host == "news") {
// Transition NextActivity
}
}
}
In case of startup after closing with the back button, the code of "Transition Next Activity" is passed many times.
I tried this but did not work.
intent.data = null
setIntent(intent)
I've answered a similar question about "extras" in an Intent in a Notification. The problem is the same. When you launch an app for the first time (in your case via deep link), Android remembers the Intent that was used to launch the app. When your user returns to the app from the "recent tasks" list, Android launches the app using the same (remembered) Intent. To get around this you have 2 options:
Add Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS in your deep-link. This will prevent the task from showing up in the list of recent tasks and therefore precent the deep-link Intent from being remembered.
Detect Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY. When the user launches an app from the list of recent tasks, Android adds this flag to the Intent that is passed to your Activity's onCreate(). You can check for the existence of this flag, and if it is set, you can clear the data from the Intent so that your app does not perform the same actions as when launched by deep-link.
See my answer here for more info: https://stackoverflow.com/a/19820057/769265
If there is an app has a login activity, and it launches by the icon click. this login activity can be launched by another intent too. the problem is when the activity is running, (launched by touching the app icon) and when it receives the different intent call it starts another login activity.
how can i launch the login activity again after closing the current running activity, when the different intent call is received to launch the login activity.
the different intent mentioned above is, when the user select an specific file with specific extension, my app must be started.
<activity
android:name=".login.Login"
android:configChanges="orientation|keyboardHidden"
android:windowSoftInputMode="adjustResize">
<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" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:scheme="content"
android:mimeType="application/octet-stream"
android:pathPattern=".*\\.chat"
tools:ignore="AppLinkUrlError" />
</intent-filter>
</activity>
The second intent is called , my app downloads the selected file and stores it in internel storage.
this is the onCreate method in the Login Activity
public void onCreate(Bundle savedInstanceState) {
if (getResources().getBoolean(R.bool.portrait_only)) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
super.onCreate(savedInstanceState);
if (isTaskRoot()) {
Uri data = getIntent().getData();
if (data != null) {
getIntent().setData(null);
try {
importData(data);
} catch (Exception e) {
// warn user about bad data here
finish();
return;
}
}
}
...................................
}
when user selects a specified file, the app launches another activity. then there are two login activities in the stack. help me to get rid of this
singleinstance, singletask solutions were tried. but when the launchingmode is set to singleinstance or singletask and the second intent call is received it does not call the
importData()
method. so the file that i want to download is not downloaded..
Here I used "singleTask" as launchMode. Then I have to use onNewIntent() when the Activity is called again. below link gives some more Explanation.
“onCreate()” method is not called from another intent filter
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
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.
I am trying to intercept a clicked URL to open my APP
<intent-filter>
<data
android:host="myurl.open"
android:path="/import"
android:scheme="http" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
In MainActivity
String linkClicked = getIntent().getDataString();
new AlertDialog.....
It almost works correctly but the problem is that:
Every new clicked link it open a new instance of my app, but I don't want this, I want it to display in the same opened instance
Example:
click myurl.open/import?=1
Open the first instance showing the dialog that the user clicked in the link
click myurl.open/import?=2
Open the first instance and display the dialog showing the new clicked URL, but its opening a new instance, so I now have 2 running apks, and if I click in the third link it will open the third, how can I make it to open only the same?
If I click in the same URL again it open the first instance opened from this URL, but it doesn't display an AlertDialog
1) To open a single instance of your app, use android:launchMode="singleTask" or android:launchMode="singleInstance" in AndroidManifest.xml in your activity tag.
2) To get the data from the new intent, just override onNewIntent() method:
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent); // to attach the new intent to your Activity
//now getIntent() will return the last data
}