Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

Send uncaught Exceptions from Android Wear to Android

This is a short Gist showing how I transmit any uncaught exceptions happening in the Wearable part of my App to the connected Smartphone/Tablet. This is necessary because Android Wear devices are not directly connected to the Internet themselves.

##Wear

  • WearApp.java
  • AndroidManifest.xml
  • ErrorService.java

##Smartphone

  • WearDataListenerService.java
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="at.maui.sample.wear" >
<uses-feature android:name="android.hardware.type.watch" />
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<application
android:name=".WearableApp"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<service android:name=".wear.service.ErrorService" android:process=":error"></service>
</application>
</manifest>
package at.maui.sample.wear.service;
import android.app.IntentService;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Build;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.Wearable;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
/**
* Created by maui on 06.07.2014.
*/
public class ErrorService extends IntentService {
public ErrorService() {
super("ErrorService");
}
private List<String> getNodes(GoogleApiClient mGoogleApiClient) {
ArrayList<String> results= new ArrayList<String>();
NodeApi.GetConnectedNodesResult nodes =
Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await();
for (Node node : nodes.getNodes()) {
results.add(node.getId());
}
return results;
}
@Override
protected void onHandleIntent(Intent intent) {
GoogleApiClient mGoogleAppiClient = new GoogleApiClient.Builder(ErrorService.this)
.addApi(Wearable.API)
.build();
mGoogleAppiClient.blockingConnect();
List<String> nodes = getNodes(mGoogleAppiClient);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(bos);
oos.writeObject(intent.getSerializableExtra("exception"));
byte[] exceptionData = bos.toByteArray();
DataMap dataMap = new DataMap();
// Add a bit of information on the Wear Device to pass a long with the exception
dataMap.putString("board", Build.BOARD);
dataMap.putString("fingerprint", Build.FINGERPRINT);
dataMap.putString("model", Build.MODEL);
dataMap.putString("manufacturer", Build.MANUFACTURER);
dataMap.putString("product", Build.PRODUCT);
dataMap.putByteArray("exception", exceptionData);
// "Fire and forget" send to connected Smartphone/Tablet using the Wearable Message API
Wearable.MessageApi.sendMessage(mGoogleAppiClient, nodes.get(0), "/wear/wear_error", dataMap.toByteArray());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (oos != null)
oos.close();
} catch (IOException exx) {
// ignore close exception
}
try {
bos.close();
} catch (IOException exx) {
// ignore close exception
}
}
}
}
package at.maui.sample.wear;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
public class WearableApp extends Application {
// Android Wear's default UncaughtExceptionHandler
private Thread.UncaughtExceptionHandler mDefaultUEH;
private Thread.UncaughtExceptionHandler mWearUEH = new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(final Thread thread, final Throwable ex) {
// Pass the exception to a Service which will send the data upstream to your Smartphone/Tablet
Intent errorIntent = new Intent(WearableApp.this, ErrorService.class);
errorIntent.putExtra("exception", ex);
startService(errorIntent);
// Let the default UncaughtExceptionHandler take it from here
mDefaultUEH.uncaughtException(thread, ex);
}
};
@Override public void onCreate() {
super.onCreate();
mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(mWearUEH);
}
}
package at.maui.bunting.data;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import com.crashlytics.android.Crashlytics;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.data.FreezableUtils;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.PutDataRequest;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
import com.squareup.picasso.Picasso;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* Created by maui on 04.07.2014.
*/
public class WearDataListenerService extends WearableListenerService {
private GoogleApiClient mGoogleApiClient;
@Override
public void onCreate() {
super.onCreate();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.build();
}
@Override
public void onMessageReceived(MessageEvent messageEvent) {
if(!mGoogleApiClient.isConnected())
mGoogleApiClient.blockingConnect();
final Uri url = Uri.parse(messageEvent.getPath());
if(messageEvent.getPath().equals("/wear/wear_error")) {
DataMap map = DataMap.fromByteArray(messageEvent.getData());
ByteArrayInputStream bis = new ByteArrayInputStream(map.getByteArray("exception"));
try {
ObjectInputStream ois = new ObjectInputStream(bis);
Throwable ex = (Throwable) ois.readObject();
Crashlytics.setBool("wear_exception", true);
Crashlytics.setString("board", map.getString("board"));
Crashlytics.setString("fingerprint", map.getString("fingerprint"));
Crashlytics.setString("model", map.getString("model"));
Crashlytics.setString("manufacturer", map.getString("manufacturer"));
Crashlytics.setString("product", map.getString("product"));
Crashlytics.logException(ex);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} else if(messageEvent.getPath().equals("/some-other-path") {
// Handle all the other events synced using the Messaging API
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.