This is my first android app attempt after reading "Android 2 Application Development" and lots of stuff online.
Here is the relevant code:
from MovieRatingsActivity.java [my main]
Intent i = new Intent(MovieRatingsActivity.this, DisplayMovies.class);
startActivity(i);
from Manifest:
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".DisplayMovies"
android:label="Display Movies" >
</activity>
note: i do not have any intent filters for the second activity. Do I need any if it is an explicit intent that I never plan on interacting with another application? I have tried with multiple combinations of different intent filters just out of spite, but its hard to have this answered, as every source I go to jumps to implicit intents and doesn't answer this question.
As for behavior:
Whether in debug mode, or run mode, when I click on the button and create the intent, the emulator switches to the second activity and displays the label at the top, but nothing else. Worse, in debugger mode, when I try to step-into startActivity(i), it just suspends the main thread and goes no where. Do you need a special debug technique for when jumping to next activity?
There is a chance that my intents are fine, my logic to display the list is wrong, but even still I would like to be able to reach the code in the debugger. I also added a System.out.printline at the beginning of the second activities OnCreate method that is not executing.
Do I need any if it is an explicit intent that I never plan on
interacting with another application?
you dont need any explicit intents in that case.
Do you need a special debug technique for when jumping to next
activity?
You could put a breakpoint in onCreate() of second activity.
Related
I have a Notification which starts an Activity. After a long press on home button and selecting my app, I want to start my main Activity again, and not this Activity started by the Notification. I tried with FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS, but this removed my whole application from the recents, and that's not what I want to achieve. How can I have my app in the recents, but have the main Activity started?
Regards
Okay, I found the solution to my problem. I started an Activity from a Notification with FLAG_ACTIVITY_NEW_TASK. But it seems to me that this Activity only gets started in an own task if affinity is different from the default affinity. So I had to add a different affinity in the manifest.
And it seems that FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS does not (as documented) exlucde the Activity from the recents, rather it excludes the whole task (not the whole application) in which the Activity gets started from the recents. And as I hadn't set a different affinity the Activity which I wanted to exclude was started in the same task (although I had set FLAG_ACTIVITY_NEW_TASK) and so my whole application (as it was running in only one task) was excluded from the recents.
Now I've set a different affinity for the Activity that gets started from the Notification and I start it with FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS. When I leave this Activity and long-press the HOME button I can choose my app and the default task is started or brought to the front.
If it's wrong what I mentioned above, feel free to clear it up ...
It's not clear to me what you want.
"How can I have my app in the recents, but have the main Activity
started?"
If you want to always start one activity using the long home-press, you can define your activity as singleTask in the manifest.
That way, when you select the shortcut in the long press HOME, it will always show the MAIN, singleTask activity. I say this because I used this behavior before once. ;-)
I believe that by using this you can still start an activity from the notification normally, using, say, Intents.
In the activity tag:
android:launchMode="singleTask"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
“My First App” has an activity that handles a “share” intent. Its activity in AndroidManifest.xml looks like this:
<activity
android:name="com.example.foo.myfirstapp.MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="image/jpeg"/>
</intent-filter>
</activity>
In KitKat, sharing an image from the album to “My First App” causes MainActivity to be part of the album’s task. This is the desired behavior.
In Lollipop, sharing an image from the album to “My First App” causes a new instance of “My First App” to be launched. If I look at the overview screen, the album task is there...and then there's a separate entry for "My First App". If I share another image, I wind up with two instances of "My First App"...etc.
Question: How do I make Lollipop process the share intent in the same way as KitKat?
Here's what I've done:
I notice that the intents sent from the Album have different flags set depending on the OS. (I got these using getIntent() and looking at mFlags.)
Kitkat: 0x80001 (524289): FLAG_GRANT_READ_URI_PERMISSION, FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
Lollipop: 0x18080001 (403177473): FLAG_GRANT_READ_URI_PERMISSION, FLAG_ACTIVITY_MULTIPLE_TASK, FLAG_ACTIVITY_NEW_DOCUMENT, FLAG_ACTIVITY_NEW_TASK
From reading http://developer.android.com/reference/android/content/Intent.html, it seems that these last three flags are causing the problem. Specifically
When paired with FLAG_ACTIVITY_MULTIPLE_TASK both of these behaviors (FLAG_ACTIVITY_NEW_DOCUMENT or FLAG_ACTIVITY_NEW_TASK) are modified to skip the search for a matching task and unconditionally start a new task.
I’ve been attempting to “override” these flags by specifying android:launchMode and android:documentLaunchMode in the activity in AndroidManifest.xml without success.
From http://developer.android.com/reference/android/R.attr.html#documentLaunchMode, using documentLaunchMode “never” seems promising, since
This activity will not be launched into a new document even if the Intent contains Intent.FLAG_ACTIVITY_NEW_DOCUMENT. This gives the activity writer ultimate control over how their activity is used.
but this didn't work.
I also considered android:taskAffinity, but there doesn’t seem to be a way to say “please prefer whatever task launched you”.
Afraid you can't do anything about this. It isn't under your control. This is a change in the way the "Album" app is launching its "share" Intent. If it doesn't want your Activity in its task, you can't force it in there.
If you have issues with having multiple instances of your "share" activity, you could declare your "share" activity as launchMode="singleTask" or launchMode="singleInstance" (depending on your needs. This may, however, break other things.
My app, running in background, at some point displays activity to purposefully interrupt user's flow. My activity starts a new task, which appears in "Recent Tasks" lists while being in foreground. Is there any way it could be prevented? Setting android:excludeFromRecents does not work - activity is not presented anymore in "Recent Tasks" only after is has been paused.
Manifest looks like:
<activity
android:name="com.example.recenttasks.MainActivity"
android:excludeFromRecents="true">
</activity>
and activity is started this way:
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
The key thing you mentioned is
appears in "Recent Tasks" lists while being in foreground
I think you can't change that behavior. I just tested on my app and the same thing happens. If I press the "recent tasks" button while having my activity in the foreground, it appears listed there. The moment I move out of it to another activity or to my phone's main screen, the activity is not listed anymore.
I also tested this on the built-in DeskClock app that comes with recent Android versions and the same behavior is present there when a new alarm is triggered. Note that the AlarmAlertFullscreen activity of that app has the same parameters you mentioned in your question.
I'm not sure you can circumvent this or why you would need to in the first place since the activity is not listed anymore once it loses the focus.
you are defined it in manifest that is enough but it is not coming..
ok..try add this flag also to your Intnet and start the Activity..
intnet.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
Should the user be able to return to it? (Meaning if it shows and user clicks recents, have they lost their chance to see the hidden activity or should it still be there?)
If they cannot return to it anyway then the best action would be to finish() the activity onPause(). This will mean that as long as you have used android:excludeFromRecents and android:noHistory="true", there will be no item in recents.
If however you do wish to return to the 'interruption' activity (but do not want a recents entry) you could consider still finishing the activity onPause - but also recording a preference flag (something like IS_INTERSTITIAL). Your other activities can then check this preference in onResume and, if it is true, send an Intent to restart the Interstitial instead - To the user it will just appear they are resuming the app in the same state as they left it (interstitial)
Edit: If the screen needs to stay (rather than be re-instantiated) it may be possible to use a DialogFragment, although then you must worry about configuration changes. There is one hack you could try (explained in this answer) -
Set your label empty By using android:label="" your recent task is excluded. however this is a definite hack which may produce inconsistent results (as I haven't tested it to be sure)
I have a dictionary-type application that accepts, via an intent filter, arbitrary text shared from other apps, e. g. the browser. The intent filter is attached to a decicated activity ("Lookup") that does some posttranslation of the shared text and invokes my main activity. The lookup activity quietly closes.
I'm testing it with the system browser on Samsung Galaxy with Android 4.0.4, and here's a funny thing I notice. On the first try, it works as expected. I tap "Share", select my app as the target, the lookup activity is invoked, then the main activity is invoked. Now, if I task-switch back to the browser and hit "Share" again on a different piece of text, the menu of sharing targets is not displayed. Instead, my main activity is resumed. Not the lookup one (that'd be reasonable), but the main one. onNewIntent() is not delivered to neither main activity nor Lookup activity.
onResume() is delivered to main, though.
However, if I tap "Back" instead of task-switching back to the browser - that is, explicitly close my main activity - on the next try, the Share operation displays the menu of targets again.
What's up with this behavior? Does the Share functionality remember the target of the last share operation and try to reuse it? If so, why won't it remember the immediate target of the share - my lookup activity? Is this documented?
EDIT: the manifest for the lookup activity goes like this:
<activity android:name=".Lookup"
android:label="#string/IDS_LOOKUPTITLE"
android:theme="#style/Theme.Transparent">
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
</activity>
When I start main activity from lookup activity, I'm trying to reuse an existing one (if any), so the flags are FLAG_ACTIVITY_REORDER_TO_FRONT|FLAG_ACTIVITY_SINGLE_TOP.
I have a simple question to solve, but I am not sure how to do it.
I have a class that extends Service that runs a thread looking for a TCP connection. If one comes in, it read an input message.
If the input message is "START", I start an activity, in this fashion:
Intent dialogIntent = new Intent(getBaseContext(), VoIPCall.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
dialogIntent.putExtra("inetAddress", clientSocket.getInetAddress());
getApplication().startActivity(dialogIntent);
While this activity is running, the Service keeps running. At some point I may reserve a "STOP". I would like to call a method in the previously created Activity but I am not sure how to interact with it.
I do not want to use a static method. How can I please do that?
Thank you very much,
EDIT: I changed my code to this:
Intent dialogIntent = new Intent("com.voip.rudy.START_CALL");
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
dialogIntent.putExtra("inetAddress", clientSocket.getInetAddress());
getApplication().startActivity(dialogIntent);
And in the manifest:
<activity android:name=".VoIPCall">
<intent-filter>
<action android:name="com.voip.rudy.START_CALL" />
<action android:name="com.voip.rudy.STOP_CALL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<category android:name="android.intent.category.DEFAULT" /> was required to avoid having it crash.
EDIT:
The solution given has fixed my issue but I wanted to actually act on member variables on that class, that are previously initialized. Say I call the constructor, then I would like to go back into this activity and act on the member variables.
The member variables are not initialized when I call one action after another, it seems to create a new activity somehow. Would there be anyway to act on the same activity, and keep the objects intact please?
James
Add the Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT flags to your intent and call startActivity with a new action or a special extra that can identify the intent.
In the activity, write a method called :
private void handleIntent(Intent intent) {
}
call this from onCreate (or onResume) using:
handleIntent(getIntent());
and also write:
#Override
protected void onNewIntent(Intent intent) {
setIntent(intent);
handleIntent(intent);
}
There are a few ways to do it, really depends on the overall structure of your application. All can work. Off the top of my head these are the methods that come to mind
1) Create a custom intent and have the activity or service react to it when the otehr sends it
2) Instead of the service, setup the logic looking for the tcp connection as an async task within the dialog activity, when you have the tcp connection you could pass it off to the service to do its work
3) Take a look at the local service and remote service SDK examples and use the callback code as the basis for passing data back to the activity. You can also call through the interface back to the service.
4) Maybe even setup a broadcast receiver 'architecture'. This has the advantage of decoupling the user activity from the service entirely. You could put some of your application logic in a service in another process, or even in a process that runs at device boot.
I think any of the techniques would work. I'm guessing that the behavior you are seeing is related to the lifecycle of the activities within android and you might need to move some of your processing to the onResume/onPause or onStart/onStop methods. If you you find that your activity onCreate is not being called, but you now your activity is active, it might jsut be that an activity instance from a previous invocation is still alive in the system. If so, it is possible that the OS is using that instead of the new activity that you want. The best way to see if this is a problem is to put some "Log.d" calls at the beginning and end of all of the activity methods that you override. You will be able to tell what is happening by watching logcat. The technique that you use may also be dependent on how synchronous you want the activity's reaction to be with the TCP event. If you want completely async you can go with a standard broadcast, or a service callback with a message send. If you want synchronous then do it with a service callback. In case you haven't seen it this SDK link has a pretty good description of the activity lifecycle http://developer.android.com/reference/android/app/Activity.html