I'm working with several applications.
To log in we uses Oauth2 with customtabs using chrome.
The "mother" application performs a login then send an intent to every application to say "perform login a preload your data in background"
From there each application opens a customtab and close it, then do its other tasks in background.
yes I know, this is ugly, 6 customtabs are being opened and closed, but it is what was asked, no other solution is wanted.
To do that I made an activity without UI.
The activity receive the intent, launch the customtabs, retrieve the authorisation_code, get the tokens, then call a service to preload data and close itself (the invisible activity close itself)
Is that bad?
I did this because it's impossible to add an intent filter to an intent service, and my chrome customtabs send a intent when it's done. so only an activity can grab it.
Thanks.
I'm guessing you are developing a multiflavored app.
It's perfectly fine to use a deeplink activity to receive the intent to retrieve the code
and finish it directly in oncreate
Related
Scenario :
In my application i have enabled app linking. So when an App link is triggered, i have set a dummy AppLinkActivity (opens as "singleTask" to avoid creation of new task) to receive and handle the url received through the app link. While handling the url, i have to check whether the app was showing the "DownloadActivity", if so then i have to show a dialog.
So when an App link is triggered, i will have the already existing task with existing activities and on top of that will be the AppLinkingActivity. In this case i have no way to know what the previous activity was, since i cannot pass anything via an intent.
What i want to do
When the AppLinkingActivity is opened via an app link, is there any way by which i can find out what was the last shown activity(of my app) before AppLinkingActivity in the same task?
--Alternatively--
If i exclude the "singleTask" in manifest then the AppLinkingActivity is opened in a new task. In this scenario, is there any way by which i can get the last shown(or topmost) activity in the previous task? If yes, i also need a way to navigate to that topmost activity in the previous task? In this scenario if i simply finish() AppLinkingActivity, then the control goes back to the which ever source that triggered the app link like browser or gmail app etc.
Is any of the above two requirements is possible?
I am new to android and I have a question
I tried to launch an activity from an application (say App B) from another application (say App A) using this code:
Intent i = new Intent();
i.setComponent(new ComponentName("com.me.b","com.me.b.MainActivity"));
startActivity(i);
This is working fine but my question is :
Why can't I call another activity from B except for its launcher?? Is ther any other way to launch B's other activities from A ??
Thanks in advance ...
You can start any activity that is exported. For an activity, that usually means that it has an <intent-filter> that describes what the activity is expecting, and you should use an Intent that matches the filter.
You cannot start an activity that is not exported. Those are internal to the app. Frequently, it would not make sense to start them anyway, as those activities will have expected the user to have visited other activities first, and so not everything will necessarily be set up properly.
This pattern is fairly common:
You cannot necessarily run some command that opens a Windows program to an arbitrary dialog, even though the program itself can display that dialog when appropriate
You cannot necessarily use a URL in a Web browser to get to some internal page within a Web app, particularly those that require authentication, even though logged-in users can navigate to that URL
And so on
I launch another app from my application.
Is there any way to trigger my app when launched app closed?!
Is it good idea to use timer and check package name ?!
Starting another activity doesn't have to be one-way. You can also start another activity and receive a result back. To receive a result, call startActivityForResult() (instead of startActivity()).
For example, your app can start a camera app and receive the captured photo as a result. Or, you might start the People app in order for the user to select a contact and you'll receive the contact details as a result.
Of course, the activity that responds must be designed to return a result. When it does, it sends the result as another Intent object. Your activity receives it in the onActivityResult() callback.
More info here.
If you launch the app with startActivityForResult, you will end up in onActivityResult in your application when it closes, that is the normal flow.
But if you want to always launch your app when the other closes, it can be done using a service, but I wouldn't recommend doing that since it's bad practise.
I am trying to open a PendingIntent that opens the Gmail App in the background through a notification.
The steps are as follows:
Show notification with action button
On click of action button (which has a PendingIntent), I want start the PendingIntent (which launches the Gmail app) but in the background.
Dismiss Notification
The notification remains the only thing that the user has seen (i.e. the UI has not changed but only the notification has itself been dismissed after clicking the action button).
It may be "hack-y" but I could also quickly open and then "minimize" the gmail app?
Any ideas?
OK, I really don't understand what you can achieve from such behavior.
you definitely could not provide any meaningful extra data on the intent (unless you are the developer of gmail, which I don't believe is the case..).
actually, if you provides intent to launch explicitly Gmail app (by specifying the package name) - your code would break if Gmail app package name would change.
now to your question:
it is possible to launch activity without bringing it to foreground:
all you have to do is add to the intent been held by the pending intent to flags: FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_MULTIPLE_TASK
FLAG_ACTIVITY_MULTIPLE_TASK flag is not recommended for use unless your application is the launcher.
gmail main activity would create in background new task, and that's it.
note that the gmail activity would not go threw the onResume and onStart callbacks (because it's not on foreground..) , so if any meaningful code happens from this callbacks - they won't be executed anyway..
UPDATE
now that I know that your purpose is to mark an emails as "read", I can tell you that any attempts to launch gmail app want do to you any good. as I mentioned, you can't pass extra meaningful data to gamil launching intent. there is simply no such API's, and launching main activity simply won't do anything that would help you.
instead, I'll suggest you to use Gmail API's for control user's inbox
I have an Android app with a stack of activities. One of the activities in the stack (let's call it LoginSettings) needs to sign into an OAuth service. I've given it a button that launches a web browser via an Intent. LoginSettings can't use the singleTask or singleInstance launch modes, because it needs to stay on top of the stack of its predecessor activities. That is, if the user presses back from LoginSettings, the prior activity in the stack needs to show up, and if the user relaunches my app later, it can't relaunch showing the previous activity in the stack. Breaking the stack in the middle like singleTask does is no use.
I've used the web browser and the trick with a custom callback URL and intent filter, but because I can't use singleTask, I can't get the result into the same instance of LoginSettings: it always creates a new activity, even if the launchMode is singleTop. The desired behaviour is that after the user logs in, the browser window goes away and the user sees LoginSettings, still with the rest of the stack behind it.
I want to use the browser rather than a WebView to authenticate: first, because it shows the user they're genuinely accessing the target website, rather than giving my app their password; second, because the user probably has saved their password in the browser anyway (or may already be logged in).
I eventually found a useful trick. When LoginSettings starts the browser, it makes sure to add the FLAG_ACTIVITY_NEW_TASK flag to the Intent that launches the browser. (This probably won't make any difference, as browsers are singleTask anyway, but it's best to be sure.) Instead of giving LoginSettings the intent filter for my custom URL, I created a new activity. This new activity appears as a dialog, and doesn't have allowTaskReparenting in the manifest. It shows a progress bar and message while an AsyncTask goes and trades in the verifier for the auth token. When the AsyncTask completes, it calls moveTaskToBack(true) and then finishes. This moves the task containing (only) the browser and the dialog to the back, revealing the previous task, which contains my stack of activities leading to LoginSettings.
In my app, both LoginSettings and this new dialog use an OOB mechanism to talk to the class that actually manages and stores the auth credentials, so LoginSettings.onResume checks with the backend whether the user is now logged in, and replaces the login button if so. As an alternative, you could use a broadcast to communicate the login event, but don't forget that LoginSettings would be in the stopped state when the broadcast happens.
In theory, this could go wrong if the browser adds the FLAG_ACTIVITY_NEW_TASK flag to the Intent it starts the custom callback URL with, but I've tested with Firefox and Chrome, and it works perfectly with them. Also, in theory, the task containing LoginSettings could be destroyed while it's in the background. This is a problem with solutions based on singleTask too: you need to be prepared for the callback URL to arrive via onCreate instead of onNewIntent if this happens. But with my solution, since the dialog completes the login and saves the credentials, when the user arrives back in LoginSettings, they'll be logged in even if the activity was recreated from scratch.