2

I am relatively new to Android programming. I have been given a task at work where I need to create a Custom Home activity launcher. I did a bit of research and found the example on the Android developer website (home sample). This was the start for my prototype.

The custom Home activity will need to require the user to authenticate (enter some simple credentials). My thought was to launch a sub-activity from the Home activity and pass back the results in the intent to the Home activity. I need to be able to capture information about these credentials and that information was going to be passed back to the Home activity. However, I have problems when trying this. I get a log in the LogCat that says the following: "Activity is launching as a new task, so canceling activity result."

I am aware of the startActivityForResult method, but that does not seem to be working for me. Here is where I launch the activity from my Home activity:

@Override
protected void onResume() {
    super.onResume();
    bindRecents();

    Intent iii = new Intent(this, Login.class);
    startActivityForResult(iii, STATIC_LOGIN_INTEGER_VALUE);
}

When that code executes, I get the above mentioned log from the ActivityManager tag.

My Login activity has a button that the user will hit once they have entered their credentials. If the credentials are good, then I try to do the following (I put in several logs so that I could try to figure out what is going on):

public void onClick(View src) {
    // check for authentic credentials
    if(IsValid())
    {
        Intent loginAuth = new Intent("Login");
        loginAuth.putExtra("userRole", userRole);

        Log.d("LOGIN", "Setting result...");
        if (getParent() == null) {
            Log.d("LOGIN", "Parent was null");
            setResult(Activity.RESULT_OK, loginAuth);
        }
        else {
            Log.d("LOGIN", "setting result on parent...");
            getParent().setResult(Activity.RESULT_OK, loginAuth);
        }

        Log.d("LOGIN", "Finishing the activity");
        finish();
    }
}

I defined these activities in my manifest file as the following:

    <activity android:name="Home"
            android:theme="@style/Theme"
            android:launchMode="singleInstance"
            android:stateNotNeeded="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.HOME"/>
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>

    <activity android:name="Login"
              android:label="Login"
              android:launchMode="singleInstance">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.HOME" />
        </intent-filter>
    </activity>

I was playing around with the intent filter on the Login activity. I had originally had it set to nothing. I also had the launchMode blank (which defaults to standard I believe). I have played around with most of these options and nothing seems to change the fact that the ActivityManager seems to want to launch the activity as a new task and wants to ignore the returned intent (which I need).

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Steve Ankeny
  • 335
  • 5
  • 18

3 Answers3

10

The problem is that you declared your activities with launchMode="singleInstance", so Android creates a new task (i.e. a new process) when it launches the Login activity. Activities in different tasks cannot return results to each other. From the Activity.startActivityForResult() docs:

For example, if the activity you are launching uses the singleTask launch mode, it will not run in your task and thus you will immediately receive a cancel result.

singleInstance is like singleTask but even more restrictive. Try removing the launchMode attribute from your manifest so that the Login activity will launch in the same task, then using FLAG_ACTIVITY_NEW_TASK when you need to launch a different activity in a separate task.

Barry

Barry Fruitman
  • 12,316
  • 13
  • 72
  • 135
  • 1
    Thanks for the answers. Changing the launch modes did nothing for me until I also changed the Home activity launch mode. I need to do a bit more digging to figure out the correct combination. We definitely do not want multiple activities of these launched. Right now I am using singleTop instead of standard. I think I need to play around with the flags a bit more for launching the activities. Right now, I am just using singleTop to get to debugging/developing the other features I need. I will re-visit this later on. I'm quickly learning the power of the manifest file ;) – Steve Ankeny Jun 23 '11 at 14:33
1

The documentation says

For example, if the activity you are launching uses the singleTask launch mode, it will not run in your task and thus you will immediately receive a cancel result.

THIS IS WRONG.

You can use the singleTask just fine, what you can't use is singleInstance.

Let's return to the problem. What is the problem?

The problem is that when you call startActivityForResult() on an activity, the caller activity and the activity you are launching must be on the same task for the startActivityForResult() to work properly that means that you can't call startActivityForResult() to an activity using the Intent.FLAG_ACTIVITY_NEW_TASK.

why singleInstance isn't working?

Because a "singleInstance" activity stands alone as the only activity in its task. If it starts another activity, that activity will be launched into a different task regardless of its launch mode — as if FLAG_ACTIVITY_NEW_TASK was in the intent. In all other respects, the "singleInstance" mode is identical to "singleTask".

Why singleTask is working?

Because singleTask doesn't require the creation of a new task for the new activities being launched.

enter image description here

I quoted from this answer to explain the difference between the two launch modes.

Community
  • 1
  • 1
Ahmed Hegazy
  • 12,395
  • 5
  • 41
  • 64
0

Have you declared the setResult(int resultCode, Intent data) in your Login activity. Android Documentation says "Note that this method should only be used with Intent protocols that are defined to return a result." If it is not or some other conditions matches as in the documentation of Activity.startActivityForResult(), it will not run in your task and thus you will immediately receive a cancel result."

Neeraj Nama
  • 1,562
  • 1
  • 18
  • 24
  • I did declare that in the above code sample (in the onClick handler). It turns out it is due to the launch mode in the manifest file. I am quickly learning that the manifest file can make/break an application :). – Steve Ankeny Jun 23 '11 at 14:35