I am trying to read a file in order to send it via Wear App, but I get an OutOfMemory exception.
File file = new File(filePath);
final FileInputStream fileInputStream = new FileInputStream(file);
byte fileContent[] = new byte[(int) file.length()]; //***BOMBS HERE***
fileInputStream.read(fileContent);
fileInputStream.close();
Asset programDataAsset = Asset.createFromBytes(fileContent);
The exception states the following:
java.lang.OutOfMemoryError: Failed to allocate a 31150467 byte allocation with 2097152 free bytes and 16MB until OOM
at com.rithmio.coach.wear.TransferService.sendAssetToMobile(TransferService.java:110)
at com.rithmio.coach.wear.TransferService.onHandleIntent(TransferService.java:84)
at com.rithmio.coach.wear.TransferService$1.run(TransferService.java:60)
at java.lang.Thread.run(Thread.java:818)
Let's solve this using the ChannelApi. We also do not have to worry about chunks like I said in my comment. Google thought ahead and made a convenience method for sending files. public abstract PendingResult sendFile (GoogleApiClient client, Uri uri)
private String pickBestNodeId(List<Node> nodes) {
String bestNodeId = null;
// Find a nearby node or pick one arbitrarily
for (Node node : nodes) {
if (node.isNearby()) {
return node.getId();
}
bestNodeId = node.getId();
}
return bestNodeId;
}
public boolean send(File f) {
GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
// Request access only to the Wearable API
.addApi(Wearable.API)
.build();
mGoogleApiClient.blockingConnect();
Channel channel = openChannel(mGoogleApiClient, pickBestNodeId(Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await()), "/your/arbitrary/application/specific/path/").await(); //NOTE THE PATH IS ARBITRARY, IT CAN BE WHATEVER YOU WANT. IT DOES NOT POINT TO ANYTHING, AND CAN EVEN BE LEFT WITH WHAT I HAVE.
boolean didSend = channel.sendFile(mGoogleApiClient, f.toURI()).await().isSuccess();
channel.close(mGoogleApiClient);
mGoogleApiClient.disconnect();
return didSend;
}
NOTE: this uses blocking methods, and should not be run in the ui thread.
If you would like the calls to be nonblocking, you should omit my usage of PendingResult.await()
, and set the result callback of PendingResult
. The callback can be set via setResultCallback(ResultCallback callback).