6

I am developing an application which needs a Google account for certain options. Options are disabled when no account is detected, but I am presenting the user to add one by asking via a popup, if user clicks yes, the activity should start. It's working fine to display the global "Add account" page, but I want to skip that uncalled for extra step. After all, why present someone with the option to add a Exchange account if a Google account is needed, that's just confusing. So I want to default to the new Google account setup page.

Java

try {
    Intent intent = new Intent();
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
    intent.setClassName( "com.google.android.gsf", "com.google.android.gsf.login.AccountIntroActivity");

    //if(getApplicationContext().getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
        getApplicationContext().startActivity(intent);
    //} else {
        //getApplicationContext().startActivity(new Intent(Settings.ACTION_ADD_ACCOUNT).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
    //}
} catch ( ActivityNotFoundException e) {
    e.printStackTrace();
}

When I run this, the following exeception is thrown:

05-29 18:24:50.741: W/System.err(10875): android.content.ActivityNotFoundException: Unable to find explicit activity class {com.google.android.gsf/com.google.android.gsf.login.AccountIntroActivity}; have you declared this activity in your AndroidManifest.xml?

Androidmanifest.xml

    <activity 
        android:name="com.google.android.gsf.login.AccountIntroActivity"/>   

QUESTION: what am I missing here?

EDIT:

I tried a different way using addAccount, this doesn't work, nothing happens, no errors are thrown, no new activity starts to add the Google account. By the way, the entire try catch block in the original version is in a AlertDialog/ listener.

AccountManager acm = AccountManager.get();
acm.addAccount("com.google", null, null, null, null, null, null);           
slinden77
  • 3,378
  • 2
  • 37
  • 35

2 Answers2

6

Ok, the problem using the AccountManager way was that the Activity context not being used by me in the method call at all, or not correctly. Given the fact it was used in a DialogInterface, this works:

private void popup() {
     AlertDialog.Builder helpBuilder = new AlertDialog.Builder(this);
     helpBuilder.setTitle("Add Gmail account");
     helpBuilder.setMessage("These options rely on a Gmail account, but you 
     don't seem to have one configured. Would you like to configure one now?");

     helpBuilder.setPositiveButton("Yes",
     new DialogInterface.OnClickListener() {
         //@Override
         public void onClick(DialogInterface dialog, int which) {
             //try/ catch block was here
             AccountManager acm = AccountManager.get(getApplicationContext());
             acm.addAccount("com.google", null, null, null, thisclassname.this, 
             null, null);
            }
     });

     helpBuilder.setNegativeButton("No", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
             // close the dialog, return to activity
         }
     });    

     AlertDialog helpDialog = helpBuilder.create();
     helpDialog.show();
}//end method

This probably needs some more work to be able to actually use the configured account name, but for now, this answers the Q.

Sadly, this requires a permission, but I guess that's just how things are

slinden77
  • 3,378
  • 2
  • 37
  • 35
4

You are effectively trying to use a private API -- the class name of the add Google account activity may change, or it may already be different on different Android versions. It is located in one of the Google services packages, and you certainly shouldn't add its name to your manifest. In short, this is a hack, don't do it. Doesn't AccountManager.addAcount("com.google",...) work for you (you need the MANAGE_ACCOUNTS permission)?

Nikolay Elenkov
  • 52,576
  • 10
  • 84
  • 84
  • I know you're right, but I still prefer my way. I tried the addAccount method, but frankly, it just didn't work for me. Aside from that, this requires an extra permission, which to me seems pointless. I can understand this permission for the addAccountExplicitly method, because this silently adds an account, but all addAccount does is invoke a new activity, which handles it own work, nothing is actually managed/ modified/ created by the application itself. But let's assume I change my mind, could you post an example that should work? I tried it, with com.google type and rest null's, didnt work – slinden77 May 30 '12 at 13:47
  • I see your point, but you are actually _adding_ an account, albeit with user interaction, so it kind of makes sense. I know it could spook some users though. I'll have to check back, but IIRC, as long as you have the permission, "com.google" and the rest `null`'s should work. What error are you getting. – Nikolay Elenkov May 30 '12 at 13:56
  • You're right, the Android developer site clearly states permissions are required to launch new activity. I kind of circumvented my problem by changing intent.setClassName(com.google.android.gsf, ...) to (com.google.android.gsf.login). My clue was in the console where I tried to figure out what was happening when I used the extra step, the global add account page. Now I have a new problem, it asks me for a password and displays an error right away about not being able to communicate with Google servers. I am getting no errors when I use the addAccount method...but still it doesn't work...thx! – slinden77 May 30 '12 at 18:06
  • PS: I hope you don't mind me marking this Q as answered, because it's not quite yet. I'm getting in the right direction, and you're really helping, but I still can't get passed the global add account page, which is what this Q tries to resolve :) Basically I answered it myself, but also not quite yet... – slinden77 May 30 '12 at 18:11
  • What exactly is the problem, how does it 'not work'? As for the question, if you find the solution, you can add an answer yourself, and then accept it. That would take this question off SO's unanswered list. – Nikolay Elenkov May 31 '12 at 01:12
  • I updated my question, it still stands, doubt I will be able to find the answer myself, struggling :) – slinden77 May 31 '12 at 08:16
  • Cf the JavaDoc for the activity parameter: 'The Activity context to use for launching a new authenticator-defined sub-Activity to prompt the user to create an account; used only to call startActivity(); if null, the prompt will not be launched directly, but the necessary Intent will be returned to the caller instead' The activity and the callback cannot both be null. In short use this: `accountManager.addAccount("com.google", null, null, null, this, null, null);` – Nikolay Elenkov May 31 '12 at 08:24
  • I've tried that in many variations, but I missed something. But again, you pushed me in the right direction. Complete Java/ Android noob here, just started 2 weeks ago, but the problem was I was calling this from within a DailogInterface. The whole idea of contexts still has to grow on me...I'll post my full method just as a reference to others...so simple when you see it :| – slinden77 May 31 '12 at 21:00