Gcm unregistration - android

I am working on GCM in android.
I am done with the registration of the device with GCM by using following code which registers the device asynchronously.
private void registerInBackground() {
new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
regid = gcm.register(SENDER_ID);
msg = "Device registered, registration ID=" + regid;
storeRegistrationId(context, regid);
msg="Registration success. Regid: "+regid;
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
// If there is an error, don't just keep trying to register.
// Require the user to click a button again, or perform
// exponential back-off.
}
return msg;
}
#Override
protected void onPostExecute(String msg) {
Log.e("GCM", msg);
}
}.execute(null, null, null);
}
registration is done in registrationActivity
Now i want to unregister the device.
Unregister command is sent by the server app, which is received on android side.
How can i unregister the device from the activity (mdmActivity) where i process the received messages.
Whether it should be asyn or sync??
Is it wrong to create an object for registrationActivity and calling a unregisterInBackground function using that object as below from mdmActivity?
RegistrationActivity reg=new RegistrationActivity();
reg.unregisterInBackground();
And the unregisterInBackground function in registrationActivity is as follows:
protected void unregisterInBackground() {
new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
gcm.unregister();
msg = "Device unregistered, registration ID=" + regid;
// delete the regID
deleteRegistrationId(context, regid);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
}
return msg;
}
#Override
protected void onPostExecute(String msg) {
Log.e("unregistration", msg);
}
}.execute(null, null, null);
}
Need your help!! Thanks in advance.

unregister() is also blocking, like register(). As such, you really need to run it in a background thread similar to the way you did with an AsyncTask.
You call it on the GCM instance, so I think it's fine to call it from whichever activity as long as you have that gcm instance.
You might want to read this before implementing the unregister functionality.

Related

When multiple apps which listen to same GCM channel are installed, How to make sure the notification is shown only once?

I'm going to publish a series of apps and I want to be able to display notifications to users who have installed any of these apps via GCM. but when there are multiple apps installed on each device, multiple notifications are displayed to users. I want to make sure that only one notification is displayed to users, regardless of count of apps they have installed.
I have tried to put a unique Id in each GCM message that I send and in the application when the Broadcast message is received save it in a file in a specific folder in internal storage, so I can keep track of the message and avoid displaying the same message from multiple apps. but I think this is unreliable and better methods should exist.
All the apps receive the messages from the same GCM channel.
I ended up using a file on external storage as a way to check wether the current GCM message is handled or not, I tested it throughly and in works.
public class GcmIntentService extends IntentService {
public static final int NOTIFICATION_ID = -3;
private NotificationManager mNotificationManager;
public static final String TAG = "CGMIntentService";
public GcmIntentService() {
super("GcmIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
// The getMessageType() intent parameter must be the intent you received
// in your BroadcastReceiver.
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty()) { // has effect of unparcelling Bundle
if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
// Post notification of received message.
sendNotification("Received: " + extras.toString(), extras);
Log.i(TAG, "Received: " + extras.toString());
}
}
// Release the wake lock provided by the WakefulBroadcastReceiver.
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
private void sendNotification(String msg, final Bundle bundle) {
ATImg atImg = new ATImg();
//use a file lock as way to check whether another app is displaying this gcm message
String fileName = DirectoryHelper.getMCDirectory() + "/" + DirectoryHelper.handledIdsFileName;
if (DirectoryHelper.isFileLocked(fileName))
return;//file is locked, it means another app has caught this gcm message prior to this app
try {
atImg.randomAccessFile = new RandomAccessFile(fileName, "rw");
atImg.lock= atImg.randomAccessFile.getChannel().lock();// lock the file so no other app access it
} catch (FileNotFoundException e) {//again this means file is locked
e.printStackTrace();
return;
} catch (IOException e) {
e.printStackTrace();
return;
}
atImg.bundle = bundle;
atImg.doInBackground("");
}
public class ATImg extends AsyncTask<String, String, String> {
Bundle bundle;
RandomAccessFile randomAccessFile;
FileLock lock;
#Override
protected void onPostExecute(String reult){
//release the lock on file
try {
lock.release();
randomAccessFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
protected String doInBackground(String... strings) {
String id = bundle.getString("id");
//CHECK IF THE MESSAGE IS HANDLED
Gson gson = new Gson();
List<String> ids = null;
try {
Type concerete = new TypeToken<List<String>>() {
}.getType();
randomAccessFile.seek(0);
ids = gson.fromJson(randomAccessFile.readUTF(), concerete);
if (ids != null && ids.contains(id)) {
return "";//the message has already been shown
}
}
catch (Exception ex){
ex.printStackTrace();
return "";
}
//write the new id to the end of the file
if (ids == null)
ids = new ArrayList<>();
ids.add(id);
try {
randomAccessFile.seek(0);
randomAccessFile.writeUTF(gson.toJson(ids));
} catch (IOException e) {
e.printStackTrace();
}
//END MASSAGE HANDLING CODE
//write code to show the message
}
}
}

how do I start the registration thread which is in another fragment

I have an app which has a main activity and two fragments running on top of it, One of the fragment is related to Google Cloud Notification registration and receiving of push notifications from gcm . Now the issue is the first time user launches the app and clicks on the notification fragment then only the process of registration with gcm starts and then he starts receiving the notifications . But I want to automatically start the registration process from the main acitvity without the wating for switching to notification fragment . How do I achieve this? I tried to make a new function in notification fragment and put all code regarding gcm registration into that function and then I tried calling that function from MainActivity but it gets the null pointer exception .. Please take a look at my code
public class NotificationFragment extends Fragment {
TextView lblMessage;
private AppPreferences _appPrefs;
public AsyncTask<Void, Void, Void> mRegisterTask;
AlertDialogManager alert = new AlertDialogManager();
ConnectionDetector cd;
public static String name;
public static String email;
public View rootView;
public NotificationFragment(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.gcm_activity_main, container, false);
return rootView;
}
#Override
public void onStart (){
super.onStart();
autoRegistrationForNotification();
}
public void autoRegistrationForNotification()
{
_appPrefs = new AppPreferences(rootView.getContext());
_appPrefs.setToZero();
cd = new ConnectionDetector(getActivity().getApplicationContext());
name = " ";
email = " ";
// Make sure the device has the proper dependencies.
//if(cd.isConnectingToInternet())
try{
GCMRegistrar.checkDevice(getActivity().getApplicationContext());
}catch(Exception e){}
// Make sure the manifest was properly set - comment out this line
// while developing the app, then uncomment it when it's ready.
//if(cd.isConnectingToInternet())
try{
GCMRegistrar.checkManifest(getActivity().getApplicationContext());
}catch(Exception e){}
lblMessage = (TextView) rootView.findViewById(R.id.lblMessage);
lblMessage.setText(_appPrefs.getMessageFromArchive());
getActivity().getApplicationContext().registerReceiver(mHandleMessageReceiver, new IntentFilter(
DISPLAY_MESSAGE_ACTION));
// Get GCM registration id
//if(cd.isConnectingToInternet()){
final String regId = GCMRegistrar.getRegistrationId(getActivity().getApplicationContext());
// Check if regid already presents
if (regId.equals("")) {
// Registration is not present, register now with GCM
// if(cd.isConnectingToInternet())
try{
GCMRegistrar.register(getActivity().getApplicationContext(), SENDER_ID);}
catch(Exception e){}
} else {
// Device is already registered on GCM
//if(cd.isConnectingToInternet())
if (GCMRegistrar.isRegisteredOnServer(getActivity().getApplicationContext())) {
// Skips registration.
// Toast.makeText(getActivity().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 = getActivity().getApplicationContext();
mRegisterTask = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
// Register on our server
// On server creates a new user
// if(cd.isConnectingToInternet())
try{
ServerUtilities.register(context, name, email, regId);}
catch(Exception e){}
return null;
}
#Override
protected void onPostExecute(Void result) {
mRegisterTask = null;
}
};
try{
// if(cd.isConnectingToInternet())
try{
mRegisterTask.execute(null, null, null);}catch(Exception e){}
}catch(Exception e){}
}
}//else ends
}
/**
* Receiving push messages
* */
public final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// _appPrefs = new AppPreferences(getActivity());
_appPrefs = new AppPreferences(rootView.getContext());
String newMessage = "";
try{
_appPrefs.incrementNotificationCount();
newMessage = intent.getExtras().getString(EXTRA_MESSAGE);
// Waking up mobile if it is sleeping
}catch(Exception e)
{
}
try{
WakeLocker.acquire(getActivity().getApplicationContext());
}catch(Exception e)
{
}
if(_appPrefs.getMessageFromArchive().length() > 800){
_appPrefs.saveMessageToArchive(" ");
}
Time now = new Time();
now.setToNow();
int month = now.month;
int day = now.monthDay;
int year = now.year;
DateFormatSymbols dfs = new DateFormatSymbols();
String[] months = dfs.getMonths();
//lblMessage.append("\n"+String.valueOf(day)+" " +months[month - 1] + " "+String.valueOf(year)+"\n"+newMessage.toString());
try{
if(newMessage!=null)
{
_appPrefs.saveMessageToArchive(_appPrefs.getMessageFromArchive().toString()+"\n _____________________ \n"+String.valueOf(day)+" " +months[month - 1] + " "+String.valueOf(year)+"\n"+newMessage.toString());
lblMessage.setText(_appPrefs.getMessageFromArchive());
}else{}
}
catch(Exception e){}
Toast.makeText(getActivity().getApplicationContext(), "New Message: " + newMessage, Toast.LENGTH_LONG).show();
try{
// Releasing wake lock
WakeLocker.release();}catch(Exception e){}
}
};
}
But I want to automatically start the registration process from the main acitvity without the wating for switching to notification fragment
If you wish to register to GCM from the main activity, even before the fragment is created, you should move the registration code to onCreate method of the activity.

Getting a null pointer for GCM registration id when called from main activity

I am making an app wherein the students will get push notification on their devices.
For this i need to login first,when login is succesful i call the register method of gcm...but when i do this i get a null pointer on my register method...
but when i call the register method on Oncreate of main activity it gives me the registration id.
Please someone suggest me how am i suppose to call the register method from main activity
Below is my code.
Async class for registration::
void registerInBackground() {
new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
regid = gcm.register(SENDER_ID);
System.out
.println("++++++++++++++++++++++++++++++THIS IS MY REG ID FROM ASYNC+++++++++++++++++++++++++"
+ regid);
msg = "Device registered, registration ID=" + regid;
if (regid == null) {
System.out
.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&REGISTRATION ID IS NULL&&&&&&&&&&&&&&&&&&&&&&&&&&&");
}
sendRegistrationIdToBackend(regid);
storeRegistrationId(context, regid);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
// if (msg == "SERVICE_NOT_FOUND") {
//
// }
// If there is an error, don't just keep trying to register.
// Require the user to click a button again, or perform
// exponential back-off.
}
// will give on screen
return msg;
}
#Override
protected void onPostExecute(String msg) {
System.out
.println("**********THIS IS POST FROM ASYNC***************************"
+ msg);
mDisplay.append(msg + "\n");
// if (msg == null) {
// registerInBackground();
// }
// mDisplay.append(msg + "\n");
}
}.execute(null, null, null);
}
The main Class from where i am call this method::
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNavigationDrawerFragment = (NavigationDrawerFragment) getSupportFragmentManager()
.findFragmentById(R.id.navigation_drawer);
mTitle = getTitle();
// Set up the drawer.
mNavigationDrawerFragment.setUp(R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout));
MainActivityPushNotification mainHttp = new MainActivityPushNotification();
mainHttp.registerInBackground();
}
The moment i run this code i get a null pointer on regid = gcm.register(SENDER_ID);
and when i run the registartion class as my startup class then i am getting my registration id.
Help would be appreciated.
This Is because of Gcm server get some time to Create registration id you have to call this for some times i mean you have to create method which get regId and call it 5 times 1 sec interval and when get RegId break loop.

java.lang.NullPointerException when execute Asynctask

I want to register the user to gcm server so I use this function :
private void registerInBackground() {
new AsyncTask<Void,Void,String>() {
#Override
protected String doInBackground(Void... params) {
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
regid = gcm.register(SENDER_ID);
msg = "Device registered, registration ID=" + regid;
// You should send the registration ID to your server over HTTP,
// so it can use GCM/HTTP or CCS to send messages to your app.
// The request to your server should be authenticated if your app
// is using accounts.
sendRegistrationIdToBackend();
// For this demo: we don't need to send it because the device
// will send upstream messages to a server that echo back the
// message using the 'from' address in the message.
// Persist the regID - no need to register again.
// storeRegistrationId(context, regid);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
// If there is an error, don't just keep trying to register.
// Require the user to click a button again, or perform
// exponential back-off.
}
return msg;
}
#Override
protected void onPostExecute(String msg) {
mDisplay.append(msg + "\n");
}
}.execute(null, null, null);
}
it is the same function as described here, so I am surprised to get an NullPOinterEXCEPTION erro, I think it is because this line: execute(null,null,null,null), but this what google give me! what should I do ?

registration id is null from gcm in android 2.3.3, 2.3.5 but it is not null and working in android 2.3.4, 4.0.4

private void registerClient() {
try {
GCMRegistrar.checkDevice(this);
GCMRegistrar.checkManifest(this);
regId = GCMRegistrar.getRegistrationId(this);
if (regId.equals("")) {
registrationStatus = "Registering...";
GCMRegistrar.register(this, "1074338555805");
regId = GCMRegistrar.getRegistrationId(this);
registrationStatus = "Registration Acquired";
sendRegistrationToServer();
} else {
registrationStatus = "Already registered";
}
} catch (Exception e) {
e.printStackTrace();
registrationStatus = e.getMessage();
}
}
registration id is null from gcm in android 2.3.3, 2.3.5 but it is not null and working in android 2.3.4, 4.0.4.
As quite clearly stated on the Google Play Services set-up guide.
https://developer.android.com/google/gcm/client.html
Application OnCreate:
// Check device for Play Services APK. If check succeeds, proceed with
// GCM registration.
if (checkPlayServices()) {
gcm = GoogleCloudMessaging.getInstance(this);
regid = getRegistrationId(context);
if (regid.isEmpty()) {
registerInBackground();
}
} else {
Log.i(TAG, "No valid Google Play Services APK found.");
}
Register in background code:
/**
* Registers the application with GCM servers asynchronously.
* <p>
* Stores the registration ID and app versionCode in the application's
* shared preferences.
*/
private void registerInBackground() {
new AsyncTask() {
#Override
protected String doInBackground(Void... params) {
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
regid = gcm.register(SENDER_ID);
msg = "Device registered, registration ID=" + regid;
// You should send the registration ID to your server over HTTP,
// so it can use GCM/HTTP or CCS to send messages to your app.
// The request to your server should be authenticated if your app
// is using accounts.
sendRegistrationIdToBackend();
// For this demo: we don't need to send it because the device
// will send upstream messages to a server that echo back the
// message using the 'from' address in the message.
// Persist the regID - no need to register again.
storeRegistrationId(context, regid);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
// If there is an error, don't just keep trying to register.
// Require the user to click a button again, or perform
// exponential back-off.
}
return msg;
}
#Override
protected void onPostExecute(String msg) {
mDisplay.append(msg + "\n");
}
}.execute(null, null, null);
...
}

Categories

Resources