user908015
user908015

Reputation:

Saving an DataItemAsset received from Android Wear

I'm relatively new to Android. I'm transferring a file from an Android Wear device to a phone, which I did through PutDataRequest. On the phone side I get a DataItemAsset which can provide me a file descriptor using Wearable.DataApi.getFdForAsset(). My question is how do I save this file to external storage?

Thank you!

Upvotes: 2

Views: 1175

Answers (1)

Ant
Ant

Reputation: 163

Here's how I managed to upload a text file from an Android Wear watch to it's paired mobile phone. There may be a simpler way, but this is what worked for me.

(1) On the watch side, create a text file, and read it into an Asset which you can put through the DataApi:

public void SendTextFile()
{
    // Get folder for output
    File sdcard = Environment.getExternalStorageDirectory();
    File dir = new File(sdcard.getAbsolutePath()+ "/MyAppFolder/");
    if (!dir.exists()) {dir.mkdirs();} // Create folder if needed
    final File file = new File(dir, "test.txt");
    if (file.exists()) file.delete();

    // Write a text file to external storage on the watch
    try {
        Date now = new Date();
        long nTime = now.getTime();
        FileOutputStream fOut = new FileOutputStream(file);
        PrintStream ps = new PrintStream(fOut);
        ps.println("Time = "+Long.toString(nTime)); // A value that changes each time
        ps.close();
    } catch (Exception e) {
    }

    // Read the text file into a byte array
    FileInputStream fileInputStream = null;
    byte[] bFile = new byte[(int) file.length()];
    try {
        fileInputStream = new FileInputStream(file);
        fileInputStream.read(bFile);
        fileInputStream.close();
    } catch (Exception e) {
    }

    // Create an Asset from the byte array, and send it via the DataApi
    Asset asset = Asset.createFromBytes(bFile);
    PutDataMapRequest dataMap = PutDataMapRequest.create("/txt");
    dataMap.getDataMap().putAsset("com.example.company.key.TXT", asset);
    PutDataRequest request = dataMap.asPutDataRequest();
    PendingResult<DataApi.DataItemResult> pendingResult = Wearable.DataApi
            .putDataItem(mGoogleApiClient, request);
}

(2) On the mobile side, receive the asset and write it back out to a file:

public void onDataChanged(DataEventBuffer dataEvents) {
    for (DataEvent event : dataEvents) {
        if (event.getType() == DataEvent.TYPE_CHANGED &&
                event.getDataItem().getUri().getPath().equals("/txt"))
        {
            // Get the Asset object
            DataMapItem dataMapItem = DataMapItem.fromDataItem(event.getDataItem());
            Asset asset = dataMapItem.getDataMap().getAsset("com.example.company.key.TXT");

            ConnectionResult result =
                    mGoogleApiClient.blockingConnect(10000, TimeUnit.MILLISECONDS);
            if (!result.isSuccess()) {return;}

            // Convert asset into a file descriptor and block until it's ready
            InputStream assetInputStream = Wearable.DataApi.getFdForAsset(
                    mGoogleApiClient, asset).await().getInputStream();
            mGoogleApiClient.disconnect();
            if (assetInputStream == null) { return; }

            // Get folder for output
            File sdcard = Environment.getExternalStorageDirectory();
            File dir = new File(sdcard.getAbsolutePath() + "/MyAppFolder/");
            if (!dir.exists()) { dir.mkdirs(); } // Create folder if needed

            // Read data from the Asset and write it to a file on external storage
            final File file = new File(dir, "test.txt");
            try {
                FileOutputStream fOut = new FileOutputStream(file);
            int nRead;
            byte[] data = new byte[16384];
                while ((nRead = assetInputStream.read(data, 0, data.length)) != -1) {
                    fOut.write(data, 0, nRead);
                }

                fOut.flush();
                fOut.close();
            }
            catch (Exception e)
            {
            }

            // Rescan folder to make it appear
            try {
                String[] paths = new String[1];
                paths[0] = file.getAbsolutePath();
                MediaScannerConnection.scanFile(this, paths, null, null);
            } catch (Exception e) {
            }
        }
    }
}

You will also need to add the following permission to your manifests at both ends to write to external storage: android.permission.WRITE_EXTERNAL_STORAGE

Note: the most frustrating thing to watch out for is this: if the data does not change, no transfer will occur. So, when you're testing if you write the same data file contents twice, it will only come across the first time - even if you deleted the file from the first run. I lost quite a few hours to this insidious feature of the DataApi ! That's why my code above is writing the current time into the text file.

Also, of course make sure that you set up the GoogleApiClient object to connect, add listeners, etc as described here: http://developer.android.com/training/wearables/data-layer/index.html

Upvotes: 4

Related Questions