Android Wearable - Data Items: Unable to receive data on mobile device - android

I am trying to transfer heart rate sensors data from watch to mobile device. On the watch(wearable) side, I am getting message stating that the data has been transferred. I have set the priority of the message(PutDataMapRequest) as urgent on the watch.
However, I am unable to receive the data on the mobile device. Following is my code for AndroidManifest.xml:
<%service android:name=".WearableListenerService1">
<%intent-filter>
<%action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
<%data android:host="*" android:scheme="wear" android:pathPrefix= "/healthcare" />
</intent-filter>
</service>
My WearableListenerService1 class is:
public class WearableListenerService1 extends WearableListenerService {
#Override
public void onMessageReceived(MessageEvent messageEvent) {
super.onMessageReceived(messageEvent);
String event = messageEvent.getPath();
Log.d("Event ", event);
String [] message = event.split("--");
Intent i = new Intent(this, MainActivity.class);
startActivity(i);
}
#Override
public void onDataChanged(DataEventBuffer dataEventBuffer) {
// super.onDataChanged(dataEventBuffer);
Log.d("Event ", "event data changed");
Intent i = new Intent(this, MainActivity.class);
startActivity(i);
}
}
I am using following libraries:
compile 'com.google.android.support:wearable:2.0.0-alpha2'
compile 'com.google.android.gms:play-services-wearable:9.4.0'

Acording to this tutorial, make sure that the applicationId in the main app and wearable app are matched (build.gradle files) in order for the WearableListenerService to fire the onDataChanged event. Because when you send some data through mobile app or wear app, it will check for the same package to pass that data. So if you give different name, you won't be able to send or receive data.
You can also check this documentation and related SO threads:
Sending messages from Android Wear to host device
Android Wear sending data to Android phone, but phone appears to never receive it

I found the issue. Android version on my Moto360 was 1.5 whereas I was using developer preview of wear 2.0 on Android Studio.

Related

Unable to register for push notifications on Android in Xamarin together with IntercomIO

I added the IntercomIO SDK to our Xamarin.Forms app through a couple binding libraries this week and I'm currently trying to get the Push Notifications to work but soon after I call PushHandlerService.Register(this) in the MainActivity the app crashes saying that it can't find the class com.google.android.gms.gcm.GcmReceiver which isn't even being caught by the try catch block around this call.
Here is the method inside the MainActivity which is responsible for setting up the push notifications on Android.
public void registerForPushNotifications()
{
try
{
GcmClient.CheckDevice(this);
GcmClient.CheckManifest(this);
//Register the app for push notifications.
PushHandlerService.Initialize(this);
//if (!GcmClient.IsRegistered(this))//Temporarily force the app to register for push notifications
{
System.Diagnostics.Debug.WriteLine("Registering");
// Register for GCM
PushHandlerService.Register(this);
}
LocalBroadcastManager lbc = LocalBroadcastManager.GetInstance(this);
PushActionReceiver rec = new PushActionReceiver(this);
lbc.RegisterReceiver(rec, new IntentFilter("pushaction"));
}
catch (Java.Net.MalformedURLException)
{
var e = new Exception("There was an error creating the Mobile Service. Verify the URL");
System.Diagnostics.Debug.Fail(String.Format(#"Exception at {0}: {1}", this.GetType().Name, e.Message));
Insights.Report(e);
}
catch (Exception e)
{
System.Diagnostics.Debug.Fail(String.Format(#"Exception at {0}: {1}", this.GetType().Name, e.Message));
if (e.GetType() != typeof(TaskCanceledException))
Insights.Report(e);
}
}
And in the Manifest I added the receiver definition for Intercom
<receiver android:name="io.intercom.android.sdk.gcm.GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND"></receiver>
The issue doesn't happen when I don't call PushHandlerService.Register(this) but then obviously I can't receive any push notifications anymore (including the ones from our own system)
What's going on here? I have the libraries and dependancies setup properly but it doesn't seem to be able to find the GcmReceiver class..
Apparently updating to the latest SDK's in the SDK Manager solved this crash. I am still not receiving any push notifications but I'm guessing this is due to a different issue. At least the app doesn't crash anymore when trying to register for the push notifications.
Dale from Intercom here. Are you using any other third party push providers, or do you have your own GCM receiver? It's possible that they are consuming our push and not passing them on. This can be difficult in Xamarin, Phonegap, Cordova ect. as often the registration and receiver services are not available. I have included below a link to our GCM doc and the section that may be most relevant to you. If this doesn't help fix the issue get in touch with us on the cordova repo: https://github.com/intercom/intercom-cordova or reach out to us in your Intercom dashboard/ email us at team#intercom.io.
We have GCM docs here: https://docs.intercom.com/configure-intercom-for-your-product-or-site/configure-intercom-for-mobile/enable-push-notifications-with-intercom-for-android-gcm
The issue that might be causing you difficulty in your setup is:
Step 7. Using Intercom with other GCM setups (Optional)
This only applies to applications that also use GCM for their own content, or use a third party service for GCM. You’ll need to update the your GcmListenerService and the class where you generate your device token.
You should have a class that generates a push device token and sends it to your backend. In addition to sending the token to your backend you will need to forward it to Intercom, like this:
private final IntercomPushClient intercomPushClient = new IntercomPushClient();
public void onHandleIntent(Intent intent) {
InstanceID instanceId = InstanceID.getInstance(this);
String senderId = "YOUR_SENDER_ID";
String token = instanceId.getToken(senderId,
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
pushClient.sendTokenToIntercom(getApplication(), token);
}
You should have a class that extends GcmListenerService. That service will consume pushes intended for Intercom. To allow us to draw the Intercom push set up your GcmListenerService, like this:
private final IntercomPushClient intercomPushClient = new IntercomPushClient();
public void onMessageReceived(String from, Bundle message) {
if (intercomPushClient.isIntercomPush(message)) {
intercomPushClient.handlePush(getApplication(), message);
} else {
//DO HOST LOGIC HERE
}
}

Two WearableListenerService. How can one send request only to other device?

please help.
I have two WearableListenerServices. The first on phone and the second on a watch. if I send asset data from wear to phone, for example:
PutDataMapRequest dataMap = PutDataMapRequest.create(AUDIO_PATH);
dataMap.getDataMap().putAsset(REC_AUDIO_KEY, asset);
dataMap.getDataMap().putLong(TIME, new Date().getTime());
dataMap.getDataMap().putString(NAME, name);
PutDataRequest request = dataMap.asPutDataRequest();
Wearable.DataApi.putDataItem(mGoogleApiClient, request).setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
#Override
public void onResult(DataApi.DataItemResult dataItemResult) {
if (!dataItemResult.getStatus().isSuccess()) {
failRecord();
}else{
successRecord(true);
}
}
});
I expect that result will be from phone, but in fact response come back from itself. The problem is that on the watch executed method onDataChanged earlier then on the Phone. How can I send request only to other device?
Thanks.
Have u cross checked the path (AUDIO_PATH) ? It should be same in onDataChanged of wearableListenerService located in phone and not to be same in onDataChanged of wearableListenerService located in Wear.
In your question you have already mentioned that u need to send request to only one side then u dont have to implement onDataChangedMethod in Sending side.

Google Hangouts breaks SMS order

I've got an app that sends a text message as a response after receiving a text message. (Auto Respond) When SMS is enabled in hangouts, my app wasn't sending its messages. I fixed that by doing this:
<intent-filter android:priority="500">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
After sending the message, my app also writes that sent message to the user's SMS log (inbox/outbox displayed by messaging apps.)
But now that my SMS receiver is higher priority than Hangouts, the sent message is written to the user's SMS log AFTER the received message when it should be the other way around.
So it shows like this:
Response Message
Received Message - this is what triggered the response
But it should be:
Received Message - triggers response
Response Message
Is there a way for me to wait for the received message to be written before writing the response message? It works fine when SMS is disabled in Hangouts. But since Hangouts is now writing that message instead of the default SMS receiver, it messes things up like crazy.
EDIT: Thanks to Keith's response, this is the code that worked for me:
context.getContentResolver().registerContentObserver(
Uri.parse("content://sms"),
true,
smsObserver);
And this class:
private class SMSObserver extends ContentObserver
{
public SMSObserver()
{
super(null);
}
#Override
public boolean deliverSelfNotifications() {
return true;
}
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
if(!selfChange)
//sendResponse
context.getContentResolver().unregisterContentObserver(this);
}
#Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
if(!selfChange)
//sendResponse
context.getContentResolver().unregisterContentObserver(this);
}
}
I'm not sure if the self change part is necessary, but it works so I'm not changing it.
Try a ContentObserver on the SMS database to listen for when Hangouts writes to the SMS content provider. This approach should be compatible with 4.4/Hangouts as well as earlier versions; you'd just wait until something is written to write your sent message.
Tested two different versions on Android 4.3, Galaxy Nexus:
context.getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, myContentObserver);
or
cursor = context.getContentResolver().query(Uri.parse("content://sms/inbox"),
new String[] { SMS_ID, SMS_ADDRESS, SMS_READ },
"read = 0",
null,
null);
cursor.registerContentObserver(myContentObserver);
But I couldn't use the non-Cursor version with sms/inbox for some reason. The downside of the Cursor-based version is that it seems to need to stay open so then you have to be sure to close it later.
Also, neither version is being called when the read status changes.

Google Cloud Messaging register AUTHENTICATION_FAILED

I want to try Google Cloud Messaging (GCM) service, and I am faced with a problem at the beginning.
I get an error AUTHENTICATION_FAILED while trying to register a device to GCM.
I searched and all I found were variations of the incorrect password. My password is correct and I am using just one account.
There are two ways to implement GCM client on Android:
GCM library with additional jar, now deprecated.
Google Play Services API
I started with the second of course and got this issue.
I thought the problem is in my phone, but then decided to try the first way, which worked!
However, it is deprecated and requires an additional jar, which doesn't seem like the right way.
In an attempt to understand the reasons for the error, I decompiled Google Play Services jar and compared it with GCM library.
It turns out they both have a similar method, something like:
void register(Context context, String senderIds) {
Intent intent = new Intent("com.google.android.c2dm.intent.REGISTER");
intent.setPackage("com.google.android.gms"); // this one row are different
setPackageNameExtra(context, intent);
intent.putExtra("sender", senderIds);
context.startService(intent);
}
The difference in one row:
In GCM library it is com.google.android.gsf, where gsf is Google Services Framework (I guess), and it works!
In Google Play Services API jar it is com.google.android.gms, And it does not work (AUTHENTICATION_FAILED error).
Then in GCM library I replaced "gsf" to "gms" and run. And I got the same AUTHENTICATION_FAILED error! If I enter another package, then it is not working.
What do I need to do to make it work? Should I set up something in the phone? Or is it a bug in Google Play Services? Have someone encountered such a problem?
Thanks in advance!
I ran into the same problem, and it doesn't seem like google is in any hurry to fix it.
I didn't want to add the deprecated client helper gcm.jar to my app, so I coded a minimal solution that works on my Android 2.3.6 Nexus One phone that fails registration as in the question above
try {
gcm = GoogleCloudMessaging.getInstance(context);
regID = gcm.register(SENDER_ID);
storeRegistrationId(regID);
msg = "Device registered, registration ID=" + regID;
sendRegistrationIdToBackend();
} catch (IOException ex) {
msg = "Exception registering for GCM :" + ex.getMessage();
// If there is an error, don't just keep trying to register.
oldSchoolRegister();
}
The AUTHENTICATION_FAILED triggers the IOException in the code above
private void oldSchoolRegister() {
Intent intent = new Intent("com.google.android.c2dm.intent.REGISTER");
intent.setPackage("com.google.android.gsf");
setRegCallbackIntent(context, intent);
intent.putExtra("sender", SENDER_ID);
context.startService(intent);
}
private static synchronized void setRegCallbackIntent(Context context, Intent intent) {
regCallback = PendingIntent.getBroadcast(context, 0, new Intent(), 0);
intent.putExtra("app", regCallback);
}
public static synchronized void cancelRegCallbackIntent() {
if (regCallback != null) {
regCallback.cancel();
regCallback = null;
}
}
I added the above code to my app. They are simplified methods from the Client Helper gcm.jar (so you don't need to add the jar to your app)
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
if (extras != null && !extras.isEmpty()) { // has effect of unparcelling Bundle
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
if (messageType != null) {
if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
showMessage(extras.getString("message")); // call your code
Logger.d(TAG, "Received message: " + message.alert + ": " + message.url);
} else if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
Logger.e(TAG, "Send error: " + extras.toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
Logger.e(TAG, "Deleted messages on server: " + extras.toString());
}
} else {
String regID = extras.getString("registration_id");
if (regID != null && !regID.isEmpty()) {
doRegistration(regID); // send to your server etc.
GCMSetup.storeRegistrationId(regID);
GCMSetup.cancelRegCallbackIntent();
}
}
}
// Release the wake lock provided by the WakefulBroadcastReceiver.
GCMBroadcastReceiver.completeWakefulIntent(intent);
}
This code is in the intent service, and has a few lines to store the ID received from GCM. As you can see only about 20 extra lines of code compared to a basic implementation, and no additional dependencies! You only need to update your AndroidManifest.xml to make sure you can receive the REGISTRATION intent.
<receiver android:name="com.camiolog.android.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION"/>
<category android:name="com.camiolog.android"/>
</intent-filter>
</receiver>
I hope this helps until google gets their act together!
This seems like a bug. Here's what an Android developer says about it in the android-gcm Google Group:
Some background: Froyo and Gingerbread registration is implemented in
GoogleServicesFramework, using the Google account for registration.
This has resulted in a lot of auth errors for people where the account
was not in a good state.
Starting with ICS, GCM doesn't depend or uses the Google account - you
can use it before you add an account or without any accounts.
The "Play Services" update is implementing the new scheme on all
devices - but it seems a small number of devices have problems with
this, we're investigating - but the numbers are far lower than those
with the old scheme.
If you want to use the code in GSF, for Froyo and Gingerbread - you
need to use the previous library, which sets package name explicitly.
The new library in GCM is using the new registration code.
The actual connection to google is following the same path - we're
gradually (and slowly) moving devices to the new code in play
services.
So far I have 2 bugreports, and we have a few suspects. We know that
if a device is not connected for >9 months it's going to be in this
state, and a factory reset will be needed.
We had some reports where a factory reset didn't solve the problem -
but I have no bugreport or information to confirm or trace this. The
only case I identified where a factory reset wouldn't help is if the
phone is sending bad information to the server in the initial checkin
- we're adding extra checks for this.
Apparently, a factory reset may solve the problem, but they're still investigating.
So it looks like the solution to avoid this problem is to fall back to the old deprecated GCM client library in case the AUTHENTICATION_FAILED error happens on FROYO and GINGERBREAD.
Here is a simple code snippet of how I upgraded the new Gcm client to fallback to use the old client:
#Override
protected void onPostExecute(Integer resultCode) {
if(resultCode == EXCEPTION_THROWED) {
//Android 2.2 gmc bug http://stackoverflow.com/questions/19269607/google-cloud-messaging-register-authentication-failed
//fall back to old deprecated GCM client library
GCMRegistrar.checkDevice(StartActivity.this);
GCMRegistrar.checkManifest(StartActivity.this);
final String registrationId = GCMRegistrar.getRegistrationId(StartActivity.this);
if (registrationId.equals("")) {
GCMRegistrar.register(StartActivity.this, SENDER_ID);
}
//Toast.makeText(context, "Orders and menus won't be sync with other devices since GoogleCloudMessaging is not working correctly on this device. Please notify the developer.", Toast.LENGTH_LONG).show();
}
}
You can find the old deprecated GCM Client helpher here: http://developer.android.com/google/gcm/helper.html
You can find the code of the GCM client on your computer on the path:
ANDROID_SDK_ROOT/extras/google/gcm-client (given you've downloaded this extra using the Android SDK Manager).
I put the old gcm client in a new package named com.google.android.gcm.deprecated to try to remember myself to not use this for other stuff.

new gcm api, GoogleCloudMessaging authentification fail on some device [duplicate]

I want to try Google Cloud Messaging (GCM) service, and I am faced with a problem at the beginning.
I get an error AUTHENTICATION_FAILED while trying to register a device to GCM.
I searched and all I found were variations of the incorrect password. My password is correct and I am using just one account.
There are two ways to implement GCM client on Android:
GCM library with additional jar, now deprecated.
Google Play Services API
I started with the second of course and got this issue.
I thought the problem is in my phone, but then decided to try the first way, which worked!
However, it is deprecated and requires an additional jar, which doesn't seem like the right way.
In an attempt to understand the reasons for the error, I decompiled Google Play Services jar and compared it with GCM library.
It turns out they both have a similar method, something like:
void register(Context context, String senderIds) {
Intent intent = new Intent("com.google.android.c2dm.intent.REGISTER");
intent.setPackage("com.google.android.gms"); // this one row are different
setPackageNameExtra(context, intent);
intent.putExtra("sender", senderIds);
context.startService(intent);
}
The difference in one row:
In GCM library it is com.google.android.gsf, where gsf is Google Services Framework (I guess), and it works!
In Google Play Services API jar it is com.google.android.gms, And it does not work (AUTHENTICATION_FAILED error).
Then in GCM library I replaced "gsf" to "gms" and run. And I got the same AUTHENTICATION_FAILED error! If I enter another package, then it is not working.
What do I need to do to make it work? Should I set up something in the phone? Or is it a bug in Google Play Services? Have someone encountered such a problem?
Thanks in advance!
I ran into the same problem, and it doesn't seem like google is in any hurry to fix it.
I didn't want to add the deprecated client helper gcm.jar to my app, so I coded a minimal solution that works on my Android 2.3.6 Nexus One phone that fails registration as in the question above
try {
gcm = GoogleCloudMessaging.getInstance(context);
regID = gcm.register(SENDER_ID);
storeRegistrationId(regID);
msg = "Device registered, registration ID=" + regID;
sendRegistrationIdToBackend();
} catch (IOException ex) {
msg = "Exception registering for GCM :" + ex.getMessage();
// If there is an error, don't just keep trying to register.
oldSchoolRegister();
}
The AUTHENTICATION_FAILED triggers the IOException in the code above
private void oldSchoolRegister() {
Intent intent = new Intent("com.google.android.c2dm.intent.REGISTER");
intent.setPackage("com.google.android.gsf");
setRegCallbackIntent(context, intent);
intent.putExtra("sender", SENDER_ID);
context.startService(intent);
}
private static synchronized void setRegCallbackIntent(Context context, Intent intent) {
regCallback = PendingIntent.getBroadcast(context, 0, new Intent(), 0);
intent.putExtra("app", regCallback);
}
public static synchronized void cancelRegCallbackIntent() {
if (regCallback != null) {
regCallback.cancel();
regCallback = null;
}
}
I added the above code to my app. They are simplified methods from the Client Helper gcm.jar (so you don't need to add the jar to your app)
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
if (extras != null && !extras.isEmpty()) { // has effect of unparcelling Bundle
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
if (messageType != null) {
if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
showMessage(extras.getString("message")); // call your code
Logger.d(TAG, "Received message: " + message.alert + ": " + message.url);
} else if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
Logger.e(TAG, "Send error: " + extras.toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
Logger.e(TAG, "Deleted messages on server: " + extras.toString());
}
} else {
String regID = extras.getString("registration_id");
if (regID != null && !regID.isEmpty()) {
doRegistration(regID); // send to your server etc.
GCMSetup.storeRegistrationId(regID);
GCMSetup.cancelRegCallbackIntent();
}
}
}
// Release the wake lock provided by the WakefulBroadcastReceiver.
GCMBroadcastReceiver.completeWakefulIntent(intent);
}
This code is in the intent service, and has a few lines to store the ID received from GCM. As you can see only about 20 extra lines of code compared to a basic implementation, and no additional dependencies! You only need to update your AndroidManifest.xml to make sure you can receive the REGISTRATION intent.
<receiver android:name="com.camiolog.android.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION"/>
<category android:name="com.camiolog.android"/>
</intent-filter>
</receiver>
I hope this helps until google gets their act together!
This seems like a bug. Here's what an Android developer says about it in the android-gcm Google Group:
Some background: Froyo and Gingerbread registration is implemented in
GoogleServicesFramework, using the Google account for registration.
This has resulted in a lot of auth errors for people where the account
was not in a good state.
Starting with ICS, GCM doesn't depend or uses the Google account - you
can use it before you add an account or without any accounts.
The "Play Services" update is implementing the new scheme on all
devices - but it seems a small number of devices have problems with
this, we're investigating - but the numbers are far lower than those
with the old scheme.
If you want to use the code in GSF, for Froyo and Gingerbread - you
need to use the previous library, which sets package name explicitly.
The new library in GCM is using the new registration code.
The actual connection to google is following the same path - we're
gradually (and slowly) moving devices to the new code in play
services.
So far I have 2 bugreports, and we have a few suspects. We know that
if a device is not connected for >9 months it's going to be in this
state, and a factory reset will be needed.
We had some reports where a factory reset didn't solve the problem -
but I have no bugreport or information to confirm or trace this. The
only case I identified where a factory reset wouldn't help is if the
phone is sending bad information to the server in the initial checkin
- we're adding extra checks for this.
Apparently, a factory reset may solve the problem, but they're still investigating.
So it looks like the solution to avoid this problem is to fall back to the old deprecated GCM client library in case the AUTHENTICATION_FAILED error happens on FROYO and GINGERBREAD.
Here is a simple code snippet of how I upgraded the new Gcm client to fallback to use the old client:
#Override
protected void onPostExecute(Integer resultCode) {
if(resultCode == EXCEPTION_THROWED) {
//Android 2.2 gmc bug http://stackoverflow.com/questions/19269607/google-cloud-messaging-register-authentication-failed
//fall back to old deprecated GCM client library
GCMRegistrar.checkDevice(StartActivity.this);
GCMRegistrar.checkManifest(StartActivity.this);
final String registrationId = GCMRegistrar.getRegistrationId(StartActivity.this);
if (registrationId.equals("")) {
GCMRegistrar.register(StartActivity.this, SENDER_ID);
}
//Toast.makeText(context, "Orders and menus won't be sync with other devices since GoogleCloudMessaging is not working correctly on this device. Please notify the developer.", Toast.LENGTH_LONG).show();
}
}
You can find the old deprecated GCM Client helpher here: http://developer.android.com/google/gcm/helper.html
You can find the code of the GCM client on your computer on the path:
ANDROID_SDK_ROOT/extras/google/gcm-client (given you've downloaded this extra using the Android SDK Manager).
I put the old gcm client in a new package named com.google.android.gcm.deprecated to try to remember myself to not use this for other stuff.

Categories

Resources