Android Wear ChannelApi examples?

3.7k views Asked by At

The latest Android Wear update comes with support for ChannelApi that can be used for sending files to/from wearable or handheld. The problem is I cannot find a single sample of how to use this functionality. The Android samples doesn't include this feature. So if anyone knows how to use the sendFile/receiveFile and can give a quick example here it would be appreciated.

3

There are 3 answers

5
Reslley Gabriel On

Take a look on this answer to know how to use the Channel API to create the channel between the devices.

After you create the googleClient and retrive the nodeId of the device you want to send the file to, basically you can use the following code on the wearable side:

//opening channel
ChannelApi.OpenChannelResult result = Wearable.ChannelApi.openChannel(googleClient, nodeId, "/mypath").await();
channel = result.getChannel(); 

//sending file
channel.sendFile(googleClient, Uri.fromFile(file));

Then, on the handheld device:

//receiving the file
@Override
public void onChannelOpened(Channel channel) {
    if (channel.getPath().equals("/mypath")) {

        file = new File("/sdcard/file.txt");

        try {
            file.createNewFile();
        } catch (IOException e) {
            //handle error
        }

        channel.receiveFile(mGoogleApiClient, Uri.fromFile(file), false);
    }
}

//when file is ready
@Override
public void onInputClosed(Channel channel, int i, int i1) {
    MainActivity.this.runOnUiThread(new Runnable() {
        public void run() {
            Toast.makeText(MainActivity.this, "File received!", Toast.LENGTH_SHORT).show();
        }
    });
}

If you need more information about this, please visit the reference site from Google

0
Richárd Bogdán On

This is just an add to the answer: also check your WearableListenerService in androidmanifest. It's intent filter should contain the com.google.android.gms.wearable.CHANNEL_EVENT action.

0
billChadwick On

I have used some code like this with success. Transfers can be fairly slow.

Both the handheld and wearable applications MUST HAVE the same applicationId in their gradle files. The wearable needs a manifest entry something like this

    <service
         android:name="com.me.myWearableListenerService"
        android:enabled="true"
         android:exported="true">

        <intent-filter>
            <!-- listeners receive events that match the action and data filters -->
             <action android:name="com.google.android.gms.wearable.CHANNEL_EVENT"/>
            <data android:scheme="wear" android:host="*" android:pathPrefix="/MyAppPath" />
        </intent-filter>

    </service>

to launch its WearableListenerService when the Handheld sends a file.

private static final String WEARABLE_FILE_COPY = "MyAppPath/FileCopy";
private void copyFileToWearable  (final File file, final String nodeId, Context ctx) {

    new Thread(new Runnable() {
        @Override
        public void run() {

            final ChannelClient cc = Wearable.getChannelClient(ctx);

            ChannelClient.ChannelCallback ccb = new ChannelClient.ChannelCallback() {

                @Override
                public void onChannelClosed(@NonNull ChannelClient.Channel channel, int i, int i1) {
                    super.onChannelClosed(channel, i, i1);
                    Log.d(TAG, "copyFileToWearable " + channel.getNodeId() + " onChannelClosed ");
                    cc.unregisterChannelCallback(this);
                }

                @Override
                public void onOutputClosed(@NonNull ChannelClient.Channel channel, int i, int i1) {
                    super.onOutputClosed(channel, i, i1);
                    Log.d(TAG, "copyFileToWearable " + channel.getNodeId() + " onOutputClosed ");
                    cc.unregisterChannelCallback(this);
                    // this is transfer success callback ...
                }
            };

            ChannelClient.Channel c;

            Log.d(TAG, "copyFileToWearable transfer file " + file.getName() +
                    " size:" + file.length()/1000000 + "Mb");
            try {
                // send the filename to the wearable with the channel open
                c = Tasks.await(cc.openChannel(nodeId, WEARABLE_FILE_COPY + "/" + file.getName()));
                Log.d(TAG, "copyFileToWearable channel opened to " + nodeId);

                Log.d(TAG, "copyFileToWearable register callback");
                Tasks.await(cc.registerChannelCallback(c, ccb));

                Log.d(TAG, "copyFileToWearable sending file " + file.getName());
                Tasks.await(cc.sendFile(c, Uri.fromFile(file)));
                // completion is indicated by onOutputClosed

            } catch (Exception e) {
                Log.w(TAG, "copyFileToWearable exception " + e.getMessage());
                cc.unregisterChannelCallback(ccb);
                // failure
            }                    
        }
    }).start();
}

call this from onChannelOpened in a WearableListenerService when c.getPath() starts with WEARABLE_FILE_COPY

private void receiveFileFromHandheld(final ChannelClient.Channel c, File myStorageLocation, Context ctx) {

    // filename sent by the handheld is at the end of the path
    String[] bits = c.getPath().split("\\/");

    // store in a suitable spot
    final String receivedFileName = myStorageLocation.getAbsolutePath() + "/" + bits[bits.length-1];

    new Thread(new Runnable() {
        @Override
        public void run() {

            final ChannelClient cc = Wearable.getChannelClient(ctx);
            ChannelClient.ChannelCallback ccb = new ChannelClient.ChannelCallback() {

                boolean mClosed = false;

                @Override
                public void onChannelClosed(@NonNull ChannelClient.Channel channel, int i, int i1) {
                    super.onChannelClosed(channel, i, i1);
                    Log.d(TAG, "receiveFileFromHandheld " + channel.getNodeId() + " onChannelClosed ");
                    if (!mClosed){
                        // failure ...
                    }
                }

                @Override
                public void onInputClosed(@NonNull ChannelClient.Channel channel, int i, int i1) {
                    super.onInputClosed(channel, i, i1);
                    Log.d(TAG, "receiveFileFromHandheld " + channel.getNodeId() + " onInputClosed ");
                    long fs = new File(receivedFileName).length();
                    Log.d(TAG, "receiveFileFromHandheld got " + receivedFileName +
                            " size:" + fs / 1000000 + "Mb");
                    cc.unregisterChannelCallback(this);
                    mClosed = true;
                    // success !
                }
            };

            try {

                Log.d(TAG, "receiveFileFromHandheld register callback");
                Tasks.await(cc.registerChannelCallback(c, ccb));
                Log.d(TAG, "receiveFileFromHandheld receiving file " + receivedFileName);
                Tasks.await(cc.receiveFile(c, Uri.fromFile(new File(receivedFileName)), false));
                // completion is indicated by onInputClosed
            } catch (Exception e) {
                Log.w(TAG, "receiveFileFromHandheld exception " + e.getMessage());
                cc.unregisterChannelCallback(ccb);

                // failure ...
            }
        }
    }
    ).start();
}