How do I send data from an android wearable device to a phone in the form of a a simple text file containing data?

3.2k views Asked by At

I have a wearable app. The app after it finishes has data like time/date, UUID, Geo location, parameters selected displayed in front of me like a Data Report or Log in several TextViews underneath each other. Like a list. I want this data to be transferred from my wearable device to my android phone.

Now I have to ask does the WearOS app the pairs the phone with the watch enables such a thing? Like can the data be sent through it? OR what exactly can I do? I read about Sync data items with the Data Layer API in the documentation, but I'm not sure if the code snippets provided would help achieve what I want.

public class MainActivity extends Activity {
    private static final String COUNT_KEY = "com.example.key.count";
    private DataClient dataClient;
    private int count = 0;
    ...
    // Create a data map and put data in it
    private void increaseCounter() {
        PutDataMapRequest putDataMapReq = PutDataMapRequest.create("/count");
        putDataMapReq.getDataMap().putInt(COUNT_KEY, count++);
        PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
        Task<DataItem> putDataTask = dataClient.putDataItem(putDataReq);
    }
  ...
}

The data I display in the textviews are called through methods that I call things like: getLocation, getUUID, getDateTime, getSelections, etc... when I click a button I call them in the setOnClickListener. I want this data in the TextViews to be placed in a file or something like that and send them over to the mobile phone from the watch when they're generated.

 private void getDateTime()
{
    SimpleDateFormat sdf_date = new SimpleDateFormat("dd/MM/yyyy");
    SimpleDateFormat sdf_time = new SimpleDateFormat("HH:mm:ss z");
    String currentDate= sdf_date.format(new Date());
    String currentTime= sdf_time.format(new Date());
    textView_date_time.setText("Date: "+currentDate+"\n"+"Time: "+currentTime);
}


 @SuppressLint("SetTextI18n")
private void getUUID()
{
// Retrieving the value using its keys the file name
// must be same in both saving and retrieving the data
        @SuppressLint("WrongConstant") SharedPreferences sh = getSharedPreferences("UUID_File", MODE_APPEND);
// The value will be default as empty string because for
// the very first time when the app is opened, there is nothing to show
        String theUUID = sh.getString(PREF_UNIQUE_ID, uniqueID);
// We can then use the data
        textView_UUID.setText("UUID: "+theUUID);
}
@SuppressLint("SetTextI18n")
private void getSelections()
{
     textView_data_selected.setText("Tool No.: "+c.getToolNo()+
             "\nTool Size: " +c.getToolSizeStr()+
             "\nFrom Mode: " +c.getCurrentModeStr()+
             "\nGoto Mode: " +c.getModeStr()+
             "\nMethod: " +c.getMethodStr()+
             "\nBit Duration: " +c.getBitDuration()+
             "\nUpper bound" +c.getUpStageValue()+
             "\nLower bound: "+c.getDownStageValue());
    
}

The above are examples of the methods I use to get the data. then I call them here:

    gps_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (Build.VERSION.SDK_INT >= 26) {
                    getLocation();
                    getDateTime();
                    getUUID();
                    getSelections();
                }
                else
                {
                    //ActivityCompat.requestPermissions(get_location.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
                    Toast.makeText(get_location.this,"Build SDK too low",Toast.LENGTH_SHORT);
                }

            }
        });

Now how do I take all this and send it over from my device to the the phone?

Note: The data report I want to send as a file, I want it done subtly like something done in the background. I don't know what else to do or where to look.

1

There are 1 answers

0
Paul Mundt On BEST ANSWER

You have two options if you want to use the Data Layer, one is to use the MessageClient API to bundle your data up in a message and send it directly to the handheld. The easiest here would be to create an arbitrary JSONObject and serialize your data as a JSON string you can stuff into a message. For example:

try {
    final JSONObject object = new JSONObject();
    object.put("heart_rate", (int) event.values[0]);
    object.put("timestamp", Instant.now().toString());
    new MessageSender("/MessageChannel", object.toString(), getApplicationContext()).start();
} catch (JSONException e) {
    Log.e(TAG, "Failed to create JSON object");
}

In my case, I do this in my onSensorChanged implementation, but you can insert this wherever you are updating your text.

MessageSender is just a threaded wrapper around the MessageClient:

import java.util.List;

class MessageSender extends Thread {
    private static final String TAG = "MessageSender";

    String path;
    String message;
    Context context;

    MessageSender(String path, String message, Context context) {
        this.path = path;
        this.message = message;
        this.context = context;
    }

    public void run() {
        try {
            Task<List<Node>> nodeListTask = Wearable.getNodeClient(context.getApplicationContext()).getConnectedNodes();
            List<Node> nodes = Tasks.await(nodeListTask);
            byte[] payload = message.getBytes();

            for (Node node : nodes) {
                String nodeId = node.getId();
                Task<Integer> sendMessageTask = Wearable.getMessageClient(context).sendMessage(nodeId, this.path, payload);

                try {
                    Tasks.await(sendMessageTask);
                } catch (Exception exception) {
                    // TODO: Implement exception handling
                    Log.e(TAG, "Exception thrown");
                }
            }
        } catch (Exception exception) {
            Log.e(TAG, exception.getMessage());
        }
    }
}

The other option is to create a nested hierarchy of data items in the Data Layer and implement DataClient.OnDataChangedListener on both sides, such that changes that are written in on one side are automatically synchronized with the other. You can find a good walkthrough on how to do that here.

For your specific case, just packing it in a JSON object would probably be the simplest. The writing out to your preferred file format you can then implement on the handheld side without needing to involve the wear side.