Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6684657
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 26, 20262026-05-26T04:57:56+00:00 2026-05-26T04:57:56+00:00

UPDATE SOLVED – Thank’s to @MusiGenesis persistence with this I solved the problem by

  • 0

UPDATE

SOLVED – Thank’s to @MusiGenesis persistence with this I solved the problem by registering a new Google mail account and a new C2DM account. After updating the relevant credentials in the web server and the android app all started working like magic.

END OF UPDATE

I’m looking for a definitive list for causes of 401 unauthorised errors when sending a push notification so I can try to eliminate my problem.

I have a google email registered with C2DM
I can use curl to get an authorisation code

I have the auth token from the registered user on my android app

Using the 2 auth tokens (refreshed) I get 401 unauthorised errors from my web server when sending a push notification request from my web server.

As far as I can tell I am doing everything I need to do so I’m looking for what I may be missing. I have scoured the internet and lots of people seem to be having the same problem with no definite answer.
Any help greatly appreciated

UPDATE

As mentioned in the answer below it seems there is a second stage required to get a registration ID which appears to be different from the auth token received by the registered user on the android app. Having looked at the jumpnote code and these two resources

http://www.vogella.de/articles/AndroidCloudToDeviceMessaging/article.html#implementation_mobileregistration

and

http://marakana.com/forums/android/general/272.html

I see no info regarding a second registration call to get a regisration ID in addition to the auth token. I’m obviously missing something and would be gratefull if someone could spell this out for me.

** UPDATE 2 **

My C2DM Receiver looks like this

public class C2DMReceiver extends C2DMBaseReceiver {
    public C2DMReceiver() {
        super(REGISTERED_GOOGLE_MAIL_ADDRESS);
    }

    @Override
    public void onRegistered(Context context, String registrationId)
            throws java.io.IOException {
        // The registrationId should be sent to your application server.
        Log.e("C2DM", "Registration ID arrived!");
        Log.e("C2DM", registrationId);
        Intent webSeverReg = new Intent(this, RegService.class);
        startService(webServerReg);     
    };

    @Override
    protected void onMessage(Context context, Intent intent) {
        Log.e("C2DM", "Message: Fantastic!!!");
        // Extract the payload from the message
        Bundle extras = intent.getExtras();
        if (extras != null) {
            System.out.println(extras.get("payload"));
            // Now do something smart based on the information
        }
    }

    @Override
    public void onError(Context context, String errorId) {
        Log.e("C2DM", "Error occured!!!");
    }
}

C2DMBaseReceiver taken from jumpnote app looks like this

/**
 * Base class for C2D message receiver. Includes constants for the
 * strings used in the protocol.
 */
public abstract class C2DMBaseReceiver extends IntentService {
    private static final String C2DM_RETRY = "com.google.android.c2dm.intent.RETRY";

    public static final String REGISTRATION_CALLBACK_INTENT = "com.google.android.c2dm.intent.REGISTRATION";
    private static final String C2DM_INTENT = "com.google.android.c2dm.intent.RECEIVE";

    // Logging tag
    private static final String TAG = "C2DM";

    // Extras in the registration callback intents.
    public static final String EXTRA_UNREGISTERED = "unregistered";

    public static final String EXTRA_ERROR = "error";

    public static final String EXTRA_REGISTRATION_ID = "registration_id";

    public static final String ERR_SERVICE_NOT_AVAILABLE = "SERVICE_NOT_AVAILABLE";
    public static final String ERR_ACCOUNT_MISSING = "ACCOUNT_MISSING";
    public static final String ERR_AUTHENTICATION_FAILED = "AUTHENTICATION_FAILED";
    public static final String ERR_TOO_MANY_REGISTRATIONS = "TOO_MANY_REGISTRATIONS";
    public static final String ERR_INVALID_PARAMETERS = "INVALID_PARAMETERS";
    public static final String ERR_INVALID_SENDER = "INVALID_SENDER";
    public static final String ERR_PHONE_REGISTRATION_ERROR = "PHONE_REGISTRATION_ERROR";

    // wakelock
    private static final String WAKELOCK_KEY = "C2DM_LIB";

    private static PowerManager.WakeLock mWakeLock;
    private final String senderId;

    /**
     * The C2DMReceiver class must create a no-arg constructor and pass the 
     * sender id to be used for registration.
     */
    public C2DMBaseReceiver(String senderId) {
        // senderId is used as base name for threads, etc.
        super(senderId);
        this.senderId = senderId;
    }

    /**
     * Called when a cloud message has been received.
     */
    protected abstract void onMessage(Context context, Intent intent);

    /**
     * Called on registration error. Override to provide better
     * error messages.
     *  
     * This is called in the context of a Service - no dialog or UI.
     */
    public abstract void onError(Context context, String errorId);

    /**
     * Called when a registration token has been received.
     */
    public void onRegistered(Context context, String registrationId) throws IOException {
        // registrationId will also be saved
    }

    /**
     * Called when the device has been unregistered.
     */
    public void onUnregistered(Context context) {
    }


    @Override
    public final void onHandleIntent(Intent intent) {
        Log.d(TAG, "@@@@ - onHandleIntent Messaging request received");
        try {
            Context context = getApplicationContext();
            if (intent.getAction().equals(REGISTRATION_CALLBACK_INTENT)) {
                handleRegistration(context, intent);
            } else if (intent.getAction().equals(C2DM_INTENT)) {
                onMessage(context, intent);
            } else if (intent.getAction().equals(C2DM_RETRY)) {
                C2DMessaging.register(context, senderId);
            }
        } finally {
            //  Release the power lock, so phone can get back to sleep.
            // The lock is reference counted by default, so multiple 
            // messages are ok.

            // If the onMessage() needs to spawn a thread or do something else,
            // it should use it's own lock.
            mWakeLock.release();
        }
    }


    /**
     * Called from the broadcast receiver. 
     * Will process the received intent, call handleMessage(), registered(), etc.
     * in background threads, with a wake lock, while keeping the service 
     * alive. 
     */
    static void runIntentInService(Context context, Intent intent) {
        if (mWakeLock == null) {
            // This is called from BroadcastReceiver, there is no init.
            PowerManager pm = 
                (PowerManager) context.getSystemService(Context.POWER_SERVICE);
            mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 
                    WAKELOCK_KEY);
        }
        mWakeLock.acquire();

        // Use a naming convention, similar with how permissions and intents are 
        // used. Alternatives are introspection or an ugly use of statics. 
        String receiver = context.getPackageName() + ".C2DMReceiver";
        intent.setClassName(context, receiver);

        context.startService(intent);

    }


    private void handleRegistration(final Context context, Intent intent) {
        final String registrationId = intent.getStringExtra(EXTRA_REGISTRATION_ID);
        Log.d(TAG, "@@@@ - HandleRegistration Messaging request received");
        String error = intent.getStringExtra(EXTRA_ERROR);
        String removed = intent.getStringExtra(EXTRA_UNREGISTERED);

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "dmControl: registrationId = " + registrationId +
                ", error = " + error + ", removed = " + removed);
        }

        if (removed != null) {
            // Remember we are unregistered
            C2DMessaging.clearRegistrationId(context);
            onUnregistered(context);
            return;
        } else if (error != null) {
            // we are not registered, can try again
            C2DMessaging.clearRegistrationId(context);
            // Registration failed
            Log.e(TAG, "Registration error " + error);
            onError(context, error);
            if ("SERVICE_NOT_AVAILABLE".equals(error)) {
                long backoffTimeMs = C2DMessaging.getBackoff(context);

                Log.d(TAG, "Scheduling registration retry, backoff = " + backoffTimeMs);
                Intent retryIntent = new Intent(C2DM_RETRY);
                PendingIntent retryPIntent = PendingIntent.getBroadcast(context, 
                        0 /*requestCode*/, retryIntent, 0 /*flags*/);

                AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
                am.set(AlarmManager.ELAPSED_REALTIME,
                        backoffTimeMs, retryPIntent);

                // Next retry should wait longer.
                backoffTimeMs *= 2;
                C2DMessaging.setBackoff(context, backoffTimeMs);
            } 
        } else {
            try {
                onRegistered(context, registrationId);
                C2DMessaging.setRegistrationId(context, registrationId);
            } catch (IOException ex) {
                Log.e(TAG, "Registration error " + ex.getMessage());
            }
        }
    }
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-26T04:57:57+00:00Added an answer on May 26, 2026 at 4:57 am

    You say you “have the auth token from the registered user on my android app”. You may have just written that incorrectly, but if you mean literally that you’re using the registered user’s auth token and not the registration id the user got back from the C2DM server, then there’s your problem right there.

    Edit: Your client app (running on the device) uses a 3-step process for C2DM: 1) call the C2DM server passing the client’s gmail account id and password, get back an auth token; 2) call the C2DM server again using the auth token from step 1, get back a registration id (which is 96-120 characters of ASCII splooge); 3) call your server app and pass the registration id obtained in step 2 (not the auth token obtained in step 1).

    When your server app then wants to push something to the client, it makes a call to the C2DM server to get an auth token (passing the email and password you used to sign up for the C2DM server, not the client user’s email and password), then uses that auth token along with the client’s registration id to execute the push.

    Edit 2: my description here of what happens on the client is wrong – the client code does not involve getting an oauth token at any point. All of that stuff is handled by the Android OS itself. This tutorial:

    http://www.vogella.de/articles/AndroidCloudToDeviceMessaging/article.html

    shows nicely how everything works for C2DM.

    Edit 3: The most common mistake I’ve seen with C2DM comes from the documentation’s use of the phrase “sender’s email”. This term refers to the gmail account that was “registered” for use with C2DM, and does not refer to the gmail account of the Android user. This gmail account is used by your web server app (along with the matching password) to get an oauth token from C2DM. This same account needs to be used by the Android client app (without the matching password, which it doesn’t know) to make the call that gets back a registrationId that it then sends to your web server.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

UPDATE: First problem solved, second one described at the bottom of this post. UPDATE2:
Update II Problem Solved but Why? This has been the biggest headache ever. My
[Update] Solved the Problem by generating a new web.config. Possible error was the second
UPDATE: Solved. Thanks BusyMark! EDIT: This is revised based on the answer below from
EDIT: Update - scroll down EDIT 2: Update - problem solved Some background information:
I experienced this problem in VS2010 before, and solved it looking at this SO
Update: Problem solved, and staying solved. If you want to see the site in
UPDATE: Solved, i'm an idiot, thank you everyone! Okay little bit weird.. I just
update SOLVED - the problem is not with my code. there is a design
UPDATE: I solved the problem myself and the answer is below. Carry on... I

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.