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 ?
Related
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
}
}
}
I have this simple function that registers the user on the Google Messaging service
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(Config.GOOGLE_PROJECT_ID);
Log.d("RegisterActivity", "registerInBackground - regId: "
+ regId);
msg = "Device registered, registration ID=" + regId;
storeRegistrationId(context, regId);
appUtil.shareRegIdWithAppServer(context, regId);
Log.d("RegisterActivity", "should be rig: " + msg);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
Log.d("RegisterActivity", "Error: " + msg);
}
Log.d("RegisterActivity", "AsyncTask completed: " + msg);
return msg;
}
#Override
protected void onPostExecute(String msg) {
Toast.makeText(getApplicationContext(),
"Registered with GCM Server." + msg, Toast.LENGTH_LONG)
.show();
}
}.execute(null, null, null);
}
Edite
private void storeRegistrationId(Context context, String regId) {
final SharedPreferences prefs = getSharedPreferences(
MainActivity.class.getSimpleName(), Context.MODE_PRIVATE);
int appVersion = getAppVersion(context);
Log.i(TAG, "Saving regId on app version " + appVersion);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(REG_ID, regId);
editor.putInt(APP_VERSION, appVersion);
editor.commit();
}
End edite
When I execute it, it successfully registers on the GCM server and the user gets his registration ID successfully. BUT I get the following exception that stops and closes the application.
E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
Process: com.example.sparr_000.newgcm, PID: 25967
java.lang.RuntimeException: An error occured while executing doInBackground()
I am new to android. I have read the documentation, watched related videos and searched online but I found no solution.
What is wrong with my code and How can I get rid off this exception and continue running my app in peace?
There could be many places where the error might be as you have code running after the registration. Try to break your code into small pieces or use a debugger to know which step fails. Like comment out storeRegistrationId(context, regId);
appUtil.shareRegIdWithAppServer(context, regId);
and try running if it works then add the next or debug the rest of the functions to know which one fails.
Instead of sending the context, get the context of you application from the current class.
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("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&®ISTRATION 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.
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.
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);
...
}