Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Programming: GCMIntentService Stuck at WakeLock

I had read the various solutions about WakeLock found here, such as adding Permission in the AndroidManifest.xml as well as ensuring the Constructor of GCMIntentService is set to public.

However, my code is still stuck at "Acquiring Wakelock"

The exact same code works seperately as an individual Android Application.

I am only encountering this error AFTER I integrate it into my Main Application.

The following are my code for GCM Intent Service:

package com.mp2012.ieatishootipostanalyzer.notifications;

import static com.mp2012.ieatishootipostanalyzer.notifications.CommonUtilities.SENDER_ID;
import static com.mp2012.ieatishootipostanalyzer.notifications.CommonUtilities.displayMessage;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

import com.google.android.gcm.GCMBaseIntentService;
import com.mp2012.ieatishootipostanalyzer.R;
import com.mp2012.ieatishootipostanalyzer.notifications.MainActivity2;

public class GCMIntentService extends GCMBaseIntentService {

private static final String TAG = "GCMIntentService";

public GCMIntentService() {
    super(SENDER_ID);
}

/**
 * Method called on device registered
 **/
@Override
protected void onRegistered(Context context, String registrationId) {
    Log.i(TAG, "Device registered: regId = " + registrationId);
    displayMessage(context, "Your device registred with GCM");
    Log.d("NAME", MainActivity2.name);
    ServerUtilities.register(context, MainActivity2.name, MainActivity2.email, registrationId);
}

/**
 * Method called on device un registred
 * */
@Override
protected void onUnregistered(Context context, String registrationId) {
    Log.i(TAG, "Device unregistered");
    displayMessage(context, getString(R.string.gcm_unregistered));
    ServerUtilities.unregister(context, registrationId);
}

/**
 * Method called on Receiving a new message
 * */
@Override
protected void onMessage(Context context, Intent intent) {
    Log.i(TAG, "Received message");
    String message = intent.getExtras().getString("price");

    displayMessage(context, message);
    // notifies user
    generateNotification(context, message);
}

/**
 * Method called on receiving a deleted message
 * */
@Override
protected void onDeletedMessages(Context context, int total) {
    Log.i(TAG, "Received deleted messages notification");
    String message = getString(R.string.gcm_deleted, total);
    displayMessage(context, message);
    // notifies user
    generateNotification(context, message);
}

/**
 * Method called on Error
 * */
@Override
public void onError(Context context, String errorId) {
    Log.i(TAG, "Received error: " + errorId);
    displayMessage(context, getString(R.string.gcm_error, errorId));
}

@Override
protected boolean onRecoverableError(Context context, String errorId) {
    // log message
    Log.i(TAG, "Received recoverable error: " + errorId);
    displayMessage(context, getString(R.string.gcm_recoverable_error,
            errorId));
    return super.onRecoverableError(context, errorId);
}

/**
 * Issues a notification to inform the user that server has sent a message.
 */
private static void generateNotification(Context context, String message) {
    int icon = R.drawable.ic_launcher;
    long when = System.currentTimeMillis();
    NotificationManager notificationManager = (NotificationManager)
            context.getSystemService(Context.NOTIFICATION_SERVICE);
    Notification notification = new Notification(icon, message, when);

    String title = context.getString(R.string.app_name);

    Intent notificationIntent = new Intent(context, MainActivity2.class);
    // set intent so it does not start a new activity
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
            Intent.FLAG_ACTIVITY_SINGLE_TOP);
    PendingIntent intent =
            PendingIntent.getActivity(context, 0, notificationIntent, 0);
    notification.setLatestEventInfo(context, title, message, intent);
    notification.flags |= Notification.FLAG_AUTO_CANCEL;

    // Play default notification sound
    notification.defaults |= Notification.DEFAULT_SOUND;

    // Vibrate if vibrate is enabled
    notification.defaults |= Notification.DEFAULT_VIBRATE;
    notificationManager.notify(0, notification);      

}

}

MainActivity

package com.mp2012.ieatishootipostanalyzer.notifications;

import static com.mp2012.ieatishootipostanalyzer.notifications.CommonUtilities.DISPLAY_MESSAGE_ACTION;
import static com.mp2012.ieatishootipostanalyzer.notifications.CommonUtilities.EXTRA_MESSAGE;
import static com.mp2012.ieatishootipostanalyzer.notifications.CommonUtilities.SENDER_ID;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gcm.GCMRegistrar;
import com.mp2012.ieatishootipostanalyzer.R;

public class MainActivity2 extends Activity {
// label to display gcm messages
TextView lblMessage;

// Asyntask
AsyncTask<Void, Void, Void> mRegisterTask;

// Alert dialog manager
AlertDialogManager alert = new AlertDialogManager();

// Connection detector
ConnectionDetector cd;

public static String name;
public static String email;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main2);

    cd = new ConnectionDetector(getApplicationContext());

    // Check if Internet present
    if (!cd.isConnectingToInternet()) {
        // Internet Connection is not present
        alert.showAlertDialog(MainActivity2.this,
                "Internet Connection Error",
                "Please connect to working Internet connection", false);
        // stop executing code by return
        return;
    }

    // Getting name, email from intent
    Intent i = getIntent();

    name = i.getStringExtra("name");
    email = i.getStringExtra("email");      

    // Make sure the device has the proper dependencies.
    GCMRegistrar.checkDevice(this);

    // Make sure the manifest was properly set - comment out this line
    // while developing the app, then uncomment it when it's ready.
    GCMRegistrar.checkManifest(this);

    lblMessage = (TextView) findViewById(R.id.lblMessage);

    registerReceiver(mHandleMessageReceiver, new IntentFilter(
            DISPLAY_MESSAGE_ACTION));

    // Get GCM registration id
    final String regId = GCMRegistrar.getRegistrationId(this);

    // Check if regid already presents
    if (regId.equals("")) {
        // Registration is not present, register now with GCM
        GCMRegistrar.register(this, SENDER_ID);
    } else {
        // Device is already registered on GCM
        if (GCMRegistrar.isRegisteredOnServer(this)) {
            // Skips registration.
            Toast.makeText(getApplicationContext(), "Already registered with GCM", Toast.LENGTH_LONG).show();
        } else {
            // Try to register again, but not in the UI thread.
            // It's also necessary to cancel the thread onDestroy(),
            // hence the use of AsyncTask instead of a raw thread.
            final Context context = this;
            mRegisterTask = new AsyncTask<Void, Void, Void>() {

                @Override
                protected Void doInBackground(Void... params) {
                    // Register on our server
                    // On server creates a new user
                    ServerUtilities.register(context, name, email, regId);
                    return null;
                }

                @Override
                protected void onPostExecute(Void result) {
                    mRegisterTask = null;
                }

            };
            mRegisterTask.execute(null, null, null);
        }
    }
}       

/**
 * Receiving push messages
 * */
private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String newMessage = intent.getExtras().getString(EXTRA_MESSAGE);
        // Waking up mobile if it is sleeping
        WakeLocker.acquire(getApplicationContext());

        /**
         * Take appropriate action on this message
         * depending upon your app requirement
         * For now i am just displaying it on the screen
         * */

        // Showing received message
        lblMessage.append(newMessage + "\n");
        Toast.makeText(getApplicationContext(), "New Message: " + newMessage, Toast.LENGTH_LONG).show();

        // Releasing wake lock
        WakeLocker.release();
    }
};

@Override
protected void onDestroy() {
    if (mRegisterTask != null) {
        mRegisterTask.cancel(true);
    }
    try {
        unregisterReceiver(mHandleMessageReceiver);
        GCMRegistrar.onDestroy(this);
    } catch (Exception e) {
        Log.e("UnRegister Receiver Error", "> " + e.getMessage());
    }
    super.onDestroy();
}

}

The following is the code for AndroidManifest xml file

<uses-sdk
    android:minSdkVersion="10"
    android:targetSdkVersion="14" />
<!-- GCM connects to Internet Services. -->
<uses-permission android:name="android.permission.INTERNET" />

<!-- GCM requires a Google account. -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />

<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />

<!-- Creates a custom permission so only this app can receive its messages. -->
<permission
    android:name="com.mp2012.ieatishootipostanalyzer.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />

<uses-permission android:name="com.mp2012.ieatishootipostanalyzer.permission.C2D_MESSAGE" />

<!-- This app has permission to register and receive data message. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<!-- Network State Permissions to detect Internet status -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<!-- Permission to vibrate -->
<uses-permission android:name="android.permission.VIBRATE" />

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >        
    <activity
        android:name=".login.DashboardActivity"
        android:label="IEatIShootIPost" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <activity
        android:name=".login.RegisterActivity"
        android:label="IEatIShootIPost" 
    />
    <activity
        android:name=".login.LogoutActivity"
        android:label="IEatIShootIPost" 
    />
    <activity
        android:name=".login.SuccessRegister"
        android:label="IEatIShootIPost" 
    />
    <activity
        android:name=".login.LoginActivity"
        android:label="IEatIShootIPost" 
    />
    <activity
        android:name=".login.CalorieProgressActivity"
        android:label="IEatIShootIPost" 
    />        
    <activity
        android:name=".login.CalculateDRCIActivity"
        android:label="IEatIShootIPost" 
    />     
    <activity
        android:name=".login.WIETActivity"
        android:label="IEatIShootIPost" 
    />     
    <activity
        android:name=".login.NewFoodActivity"
        android:label="IEatIShootIPost" 
    />     
    <activity
        android:name=".login.PieChartActivity"
        android:label="IEatIShootIPost" 
    />     
    <activity
        android:name="org.achartengine.GraphicalActivity"
        android:label="IEatIShootIPost" 
    />     
    <activity
        android:name=".facebook.MainActivity"
        android:label="IEatIShootIPost" 
    />    
    <activity
        android:name=".notifications.MainActivity2"
        android:configChanges="orientation|keyboardHidden"
        android:label="IEatIShootIPost" 
    />    
    <activity
        android:name=".notifications.RegisterActivity"
        android:label="IEatIShootIPost" 
    />     
    <activity
        android:name=".login.DashboardBurnCalorieActivity"
        android:label="IEatIShootIPost" 
    />  
    <activity
        android:name=".login.ProgressBurnCalorieActivity"
        android:label="IEatIShootIPost" 
    />     

     <receiver
        android:name="com.google.android.gcm.GCMBroadcastReceiver"
        android:permission="com.google.android.c2dm.permission.SEND" >
        <intent-filter>

            <!-- Receives the actual messages. -->
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <!-- Receives the registration id. -->
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

            <category android:name="com.mp2012.ieatishootipostanalyzer" />
        </intent-filter>
    </receiver>

    <service android:name=".notifications.GCMIntentService" />
</application>

Last but not least, the error from logcat

Registering app com.mp2012.ieatishootipostanalyzer of senders 74463753470
onReceive: com.google.android.com.c2dm.intent.REGISTRATION
GCM IntentService class: com.mp2012.ieatishootipostanalyzer.GCMIntentService
Acquiring wakelock

and it hangs....

Thanks !

like image 514
user1859057 Avatar asked Feb 19 '23 01:02

user1859057


2 Answers

Keep all the GCM related class in the main package, i.e where u r calling gcm registration. like this in your project package name com.mp2012.ieatishootipostanalyzer.

like image 107
RajaReddy PolamReddy Avatar answered Mar 05 '23 12:03

RajaReddy PolamReddy


It may be the case that there are lot more packages under the main package and the GCM code need to put under another package. For example com.mp2012.ieatishootipostanalyzer.notification. This also can be done but you need to edit the GCM code provided by google cloud message system. This is in the GCMBroadcastReceiver:

protected String getGCMIntentServiceClassName(Context context) 
{
    String className = context.getPackageName() +".notification"+DEFAULT_INTENT_SERVICE_CLASS_NAME;

    return className;
}

The the system will work.

like image 25
mahbubcsedu Avatar answered Mar 05 '23 12:03

mahbubcsedu