AndroidWearで取得した加速度をスマホに送信して、リアルタイムにグラフ描画するアプリを作ります。
(前編)ではスマートウォッチで取得した加速度をスマートフォンへ送信する処理を書きました。
この(後編)ではスマートウォッチから受け取った加速度をMPAndroidChartというライブラリを使ってリアルタイムにグラフ描画します。
手順
wear側(前編)
1.加速度データ取得
2.加速度データ送信
mobile側(後編)※今回
3.加速度データ受信
4.加速度をグラフにプロット
3.加速度データ受信
ウェアラブルからのデータを受け取るため、GoogleApiClientを使います。
-
GoogleApiClientのインスタンスを作成し、
-
GoogleApiClientに接続して、
-
GoogleApiClientの結果を受け取る。
という流れです。
3.1.GoogleApiClientのインスタンスを作成
onCreate内でGoogleApiClientのインスタンスを作成します。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//GoogleApiClientインスタンス生成
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "onConnectionFailed:" + connectionResult.toString());
mChart = (LineChart) findViewById(R.id.lineChart);
mChart.setDescription(null); // 表のタイトルを空にする
mChart.setData(new LineData()); // 空のLineData型インスタンスを追加
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//GoogleApiClientインスタンス生成
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "onConnectionFailed:" + connectionResult.toString());
}
})
.addApi(Wearable.API)
.build();
mChart = (LineChart) findViewById(R.id.lineChart);
mChart.setDescription(null); // 表のタイトルを空にする
mChart.setData(new LineData()); // 空のLineData型インスタンスを追加
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//GoogleApiClientインスタンス生成
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "onConnectionFailed:" + connectionResult.toString());
}
})
.addApi(Wearable.API)
.build();
mChart = (LineChart) findViewById(R.id.lineChart);
mChart.setDescription(null); // 表のタイトルを空にする
mChart.setData(new LineData()); // 空のLineData型インスタンスを追加
}
3.2.GoogleApiClientに接続
onStart内で記述します。
protected void onStart() {
mGoogleApiClient.connect();
@Override
protected void onStart() {
super.onStart();
//GoogleApiClient接続
mGoogleApiClient.connect();
}
@Override
protected void onStart() {
super.onStart();
//GoogleApiClient接続
mGoogleApiClient.connect();
}
3.3.GoogleApiClientの結果を受け取る。
public void onConnected(Bundle bundle) {
//GoogleApiClient 接続成功時に呼ばれます。
Log.d(TAG, "onConnected");
Wearable.MessageApi.addListener(mGoogleApiClient, this);
public void onConnectionSuspended(int i) {
Log.d(TAG, "onConnectionSuspended");
public void onMessageReceived(MessageEvent messageEvent) {
xTextView.setText(messageEvent.getPath());
//受け取ったデータmsgはコンマ区切りのcsv形式なので、value[]にそれぞれ格納します。
String msg = messageEvent.getPath();
String[] value = msg.split(",", 0);
@Override
public void onConnected(Bundle bundle) {
//GoogleApiClient 接続成功時に呼ばれます。
Log.d(TAG, "onConnected");
Wearable.MessageApi.addListener(mGoogleApiClient, this);
}
@Override
public void onConnectionSuspended(int i) {
//接続中断時に呼ばれます。
Log.d(TAG, "onConnectionSuspended");
}
@Override
public void onMessageReceived(MessageEvent messageEvent) {
//メッセージ(データ)が来たら呼ばれます。
xTextView.setText(messageEvent.getPath());
//受け取ったデータmsgはコンマ区切りのcsv形式なので、value[]にそれぞれ格納します。
String msg = messageEvent.getPath();
String[] value = msg.split(",", 0);
}
@Override
public void onConnected(Bundle bundle) {
//GoogleApiClient 接続成功時に呼ばれます。
Log.d(TAG, "onConnected");
Wearable.MessageApi.addListener(mGoogleApiClient, this);
}
@Override
public void onConnectionSuspended(int i) {
//接続中断時に呼ばれます。
Log.d(TAG, "onConnectionSuspended");
}
@Override
public void onMessageReceived(MessageEvent messageEvent) {
//メッセージ(データ)が来たら呼ばれます。
xTextView.setText(messageEvent.getPath());
//受け取ったデータmsgはコンマ区切りのcsv形式なので、value[]にそれぞれ格納します。
String msg = messageEvent.getPath();
String[] value = msg.split(",", 0);
}
ここまでで、ウェアラブルで取得し送られて来た加速度データを、スマホ側で取得できるようになりました。
4.加速度をグラフにプロット
最後に取得した加速度データをMPAndroidChartを使ってグラフにプロットしていきます。
グラフ描画にはMPAndroidChartライブラリを用います。
導入はとても簡単です。
MPAndroidChart導入
プロジェクト(ルート直下)のbuild.gradle内に下記を設定します。
ハイライトが追記部分です。
allprojects {
repositories {
jcenter()
maven {
url "http://jitpack.io"
}
}
}
allprojects {
repositories {
jcenter()
maven {
url "http://jitpack.io"
}
}
}
mobileのbuild.gradle内に下記を設定します。
compile 'com.github.PhilJay:MPAndroidChart:v3.0.1'
dependencies {
compile 'com.github.PhilJay:MPAndroidChart:v3.0.1'
}
dependencies {
compile 'com.github.PhilJay:MPAndroidChart:v3.0.1'
}
レイアウト
レイアウトファイルでグラフを表示します。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.matu_mio.graphdraw.MainActivity">
<com.github.mikephil.charting.charts.LineChart
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/lineChart"/>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/xValue"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/yValue"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</android.support.constraint.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.matu_mio.graphdraw.MainActivity">
<com.github.mikephil.charting.charts.LineChart
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/lineChart"/>
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/xValue"
android:layout_below="@+id/textView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/yValue"
android:layout_below="@+id/xValue"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/zValue"
android:layout_below="@+id/yValue"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</android.support.constraint.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.matu_mio.graphdraw.MainActivity">
<com.github.mikephil.charting.charts.LineChart
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/lineChart"/>
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/xValue"
android:layout_below="@+id/textView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/yValue"
android:layout_below="@+id/xValue"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/zValue"
android:layout_below="@+id/yValue"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</android.support.constraint.ConstraintLayout>
これでスマートウォッチで取得した加速度がリアルタイムでグラフ描画できました!
最後にソースコード
wear
mobile
ActivityMain.java(wear)
package com.example.matu_mio.graphdraw;
import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.support.wearable.activity.WearableActivity;
import android.support.wearable.view.BoxInsetLayout;
import android.support.wearable.view.WatchViewStub;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.Wearable;
import java.text.SimpleDateFormat;
public class MainActivity extends Activity implements SensorEventListener {
private final String TAG = MainActivity.class.getName();
private final float GAIN = 0.9f;
private TextView mTextView;
private SensorManager mSensorManager;
private GoogleApiClient mGoogleApiClient;
//final DateFormat df = new SimpleDateFormat("HH:mm:ssSSS");
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mTextView = (TextView) findViewById(R.id.text);
mTextView.setTextSize(30.0f);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
public void onConnected(Bundle bundle) {
Log.d(TAG, "onConnected");
// NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await();
Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).setResultCallback(new ResultCallback<NodeApi.GetConnectedNodesResult>() {
public void onResult(NodeApi.GetConnectedNodesResult nodes) {
if (nodes.getNodes().size() > 0) {
mNode = nodes.getNodes().get(0).getId();
public void onConnectionSuspended(int i) {
Log.d(TAG, "onConnectionSuspended");
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "onConnectionFailed : " + connectionResult.toString());
protected void onResume() {
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
mGoogleApiClient.connect();
protected void onPause() {
mSensorManager.unregisterListener(this);
mGoogleApiClient.disconnect();
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
//x = (x * GAIN + event.values[0] * (1 - GAIN));
//y = (y * GAIN + event.values[1] * (1 - GAIN));
//z = (z * GAIN + event.values[2] * (1 - GAIN));
mTextView.setText(String.format("X : %f\nY : %f\nZ : %f" , x, y, z));
String SEND_DATA = x + "," + y + "," + z;
Wearable.MessageApi.sendMessage(mGoogleApiClient, mNode, SEND_DATA, null).setResultCallback(new ResultCallback<MessageApi.SendMessageResult>() {
public void onResult(MessageApi.SendMessageResult result) {
if (!result.getStatus().isSuccess()) {
Log.d(TAG, "ERROR : failed to send Message" + result.getStatus());
public void onAccuracyChanged(Sensor sensor, int accuracy) {
package com.example.matu_mio.graphdraw;
import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.support.wearable.activity.WearableActivity;
import android.support.wearable.view.BoxInsetLayout;
import android.support.wearable.view.WatchViewStub;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.Wearable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class MainActivity extends Activity implements SensorEventListener {
private final String TAG = MainActivity.class.getName();
private final float GAIN = 0.9f;
private TextView mTextView;
private SensorManager mSensorManager;
private GoogleApiClient mGoogleApiClient;
private String mNode;
private float x,y,z;
int count = 0;
//final DateFormat df = new SimpleDateFormat("HH:mm:ssSSS");
private Date date;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mTextView = (TextView) findViewById(R.id.text);
mTextView.setTextSize(30.0f);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle bundle) {
Log.d(TAG, "onConnected");
// NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await();
Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).setResultCallback(new ResultCallback<NodeApi.GetConnectedNodesResult>() {
@Override
public void onResult(NodeApi.GetConnectedNodesResult nodes) {
//Nodeは1個に限定
if (nodes.getNodes().size() > 0) {
mNode = nodes.getNodes().get(0).getId();
}
}
});
}
@Override
public void onConnectionSuspended(int i) {
Log.d(TAG, "onConnectionSuspended");
}
})
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "onConnectionFailed : " + connectionResult.toString());
}
})
.build();
}
@Override
protected void onResume() {
super.onResume();
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
mGoogleApiClient.connect();
}
@Override
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
mGoogleApiClient.disconnect();
}
@Override
public void onSensorChanged(SensorEvent event) {
if(count>= 2) {
count = 0;
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
//x = (x * GAIN + event.values[0] * (1 - GAIN));
//y = (y * GAIN + event.values[1] * (1 - GAIN));
//z = (z * GAIN + event.values[2] * (1 - GAIN));
x = event.values[0];
y = event.values[1];
z = event.values[2];
if (mTextView != null)
mTextView.setText(String.format("X : %f\nY : %f\nZ : %f" , x, y, z));
//転送セット
String SEND_DATA = x + "," + y + "," + z;
if (mNode != null) {
Wearable.MessageApi.sendMessage(mGoogleApiClient, mNode, SEND_DATA, null).setResultCallback(new ResultCallback<MessageApi.SendMessageResult>() {
@Override
public void onResult(MessageApi.SendMessageResult result) {
if (!result.getStatus().isSuccess()) {
Log.d(TAG, "ERROR : failed to send Message" + result.getStatus());
}
}
});
}
}
}else count++;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
package com.example.matu_mio.graphdraw;
import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.support.wearable.activity.WearableActivity;
import android.support.wearable.view.BoxInsetLayout;
import android.support.wearable.view.WatchViewStub;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.Wearable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class MainActivity extends Activity implements SensorEventListener {
private final String TAG = MainActivity.class.getName();
private final float GAIN = 0.9f;
private TextView mTextView;
private SensorManager mSensorManager;
private GoogleApiClient mGoogleApiClient;
private String mNode;
private float x,y,z;
int count = 0;
//final DateFormat df = new SimpleDateFormat("HH:mm:ssSSS");
private Date date;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mTextView = (TextView) findViewById(R.id.text);
mTextView.setTextSize(30.0f);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle bundle) {
Log.d(TAG, "onConnected");
// NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await();
Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).setResultCallback(new ResultCallback<NodeApi.GetConnectedNodesResult>() {
@Override
public void onResult(NodeApi.GetConnectedNodesResult nodes) {
//Nodeは1個に限定
if (nodes.getNodes().size() > 0) {
mNode = nodes.getNodes().get(0).getId();
}
}
});
}
@Override
public void onConnectionSuspended(int i) {
Log.d(TAG, "onConnectionSuspended");
}
})
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "onConnectionFailed : " + connectionResult.toString());
}
})
.build();
}
@Override
protected void onResume() {
super.onResume();
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
mGoogleApiClient.connect();
}
@Override
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
mGoogleApiClient.disconnect();
}
@Override
public void onSensorChanged(SensorEvent event) {
if(count>= 2) {
count = 0;
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
//x = (x * GAIN + event.values[0] * (1 - GAIN));
//y = (y * GAIN + event.values[1] * (1 - GAIN));
//z = (z * GAIN + event.values[2] * (1 - GAIN));
x = event.values[0];
y = event.values[1];
z = event.values[2];
if (mTextView != null)
mTextView.setText(String.format("X : %f\nY : %f\nZ : %f" , x, y, z));
//転送セット
String SEND_DATA = x + "," + y + "," + z;
if (mNode != null) {
Wearable.MessageApi.sendMessage(mGoogleApiClient, mNode, SEND_DATA, null).setResultCallback(new ResultCallback<MessageApi.SendMessageResult>() {
@Override
public void onResult(MessageApi.SendMessageResult result) {
if (!result.getStatus().isSuccess()) {
Log.d(TAG, "ERROR : failed to send Message" + result.getStatus());
}
}
});
}
}
}else count++;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
activity_main.xml(wear)
<?xml version="1.0" encoding="utf-8"?>
<android.support.wearable.view.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.matu_mio.graphdraw.MainActivity"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|start"
android:textColor="@android:color/white"
</android.support.wearable.view.BoxInsetLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.wearable.view.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.matu_mio.graphdraw.MainActivity"
tools:deviceIds="wear">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_world"
app:layout_box="all" />
<TextView
android:id="@+id/clock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|start"
android:textColor="@android:color/white"
app:layout_box="all" />
</android.support.wearable.view.BoxInsetLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.wearable.view.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.matu_mio.graphdraw.MainActivity"
tools:deviceIds="wear">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_world"
app:layout_box="all" />
<TextView
android:id="@+id/clock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|start"
android:textColor="@android:color/white"
app:layout_box="all" />
</android.support.wearable.view.BoxInsetLayout>
MainActivity.java(mobile)
package com.example.matu_mio.graphdraw;
import android.app.ActionBar;
import android.app.Activity;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.WindowManager;
import android.widget.TextView;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.Wearable;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
public class MainActivity extends Activity implements GoogleApiClient.ConnectionCallbacks, MessageApi.MessageListener{
private static final String TAG = MainActivity.class.getName();
private GoogleApiClient mGoogleApiClient;
String[] names = new String[]{"x-value", "y-value", "z-value"};
int[] colors = new int[]{Color.RED, Color.GREEN, Color.BLUE};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
xTextView = (TextView)findViewById(R.id.xValue);
yTextView = (TextView)findViewById(R.id.yValue);
zTextView = (TextView)findViewById(R.id.zValue);
ActionBar ab = getActionBar();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "onConnectionFailed:" + connectionResult.toString());
mChart = (LineChart) findViewById(R.id.lineChart);
mChart.setDescription(null); // 表のタイトルを空にする
mChart.setData(new LineData()); // 空のLineData型インスタンスを追加
protected void onStart() {
mGoogleApiClient.connect();
protected void onStop() {
if (null != mGoogleApiClient && mGoogleApiClient.isConnected()) {
Wearable.MessageApi.removeListener(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
//getMenuInflater().inflate(R.menu.my, menu);
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//if (id == R.id.action_settings) {
return super.onOptionsItemSelected(item);
public void onConnected(Bundle bundle) {
Log.d(TAG, "onConnected");
Wearable.MessageApi.addListener(mGoogleApiClient, this);
public void onConnectionSuspended(int i) {
Log.d(TAG, "onConnectionSuspended");
public void onMessageReceived(MessageEvent messageEvent) {
xTextView.setText(messageEvent.getPath());
String msg = messageEvent.getPath();
String[] value = msg.split(",", 0);
xTextView.setText(String.valueOf(value[0]));
yTextView.setText(String.valueOf(value[1]));
zTextView.setText(String.valueOf(value[2]));
//x = Integer.parseInt(value[0]);
//y = Integer.parseInt(value[1]);
//z = Integer.parseInt(value[2]);
LineData data = mChart.getLineData();
for (int i = 0; i < 3; i++) {
ILineDataSet set = data.getDataSetByIndex(i);
set = createSet(names[i], colors[i]);
data.addEntry(new Entry(set.getEntryCount(),Float.parseFloat(value[i])), i);
data.notifyDataChanged();
mChart.notifyDataSetChanged();
mChart.setVisibleXRangeMaximum(50);
mChart.moveViewToX(data.getEntryCount());
private LineDataSet createSet(String label, int color) {
LineDataSet set = new LineDataSet(null, label);
set.setDrawCircles(false);
set.setDrawValues(false);
package com.example.matu_mio.graphdraw;
import android.app.ActionBar;
import android.app.Activity;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.WindowManager;
import android.widget.TextView;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.Wearable;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
public class MainActivity extends Activity implements GoogleApiClient.ConnectionCallbacks, MessageApi.MessageListener{
private static final String TAG = MainActivity.class.getName();
private GoogleApiClient mGoogleApiClient;
TextView xTextView;
TextView yTextView;
TextView zTextView;
LineChart mChart;
int x,y,z;
String[] names = new String[]{"x-value", "y-value", "z-value"};
int[] colors = new int[]{Color.RED, Color.GREEN, Color.BLUE};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
xTextView = (TextView)findViewById(R.id.xValue);
yTextView = (TextView)findViewById(R.id.yValue);
zTextView = (TextView)findViewById(R.id.zValue);
ActionBar ab = getActionBar();
//ab.hide();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "onConnectionFailed:" + connectionResult.toString());
}
})
.addApi(Wearable.API)
.build();
mChart = (LineChart) findViewById(R.id.lineChart);
mChart.setDescription(null); // 表のタイトルを空にする
mChart.setData(new LineData()); // 空のLineData型インスタンスを追加
}
@Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
@Override
protected void onStop() {
super.onStop();
if (null != mGoogleApiClient && mGoogleApiClient.isConnected()) {
Wearable.MessageApi.removeListener(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
//getMenuInflater().inflate(R.menu.my, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//if (id == R.id.action_settings) {
// return true;
//}
return super.onOptionsItemSelected(item);
}
@Override
public void onConnected(Bundle bundle) {
Log.d(TAG, "onConnected");
Wearable.MessageApi.addListener(mGoogleApiClient, this);
}
@Override
public void onConnectionSuspended(int i) {
Log.d(TAG, "onConnectionSuspended");
}
@Override
public void onMessageReceived(MessageEvent messageEvent) {
xTextView.setText(messageEvent.getPath());
String msg = messageEvent.getPath();
String[] value = msg.split(",", 0);
xTextView.setText(String.valueOf(value[0]));
yTextView.setText(String.valueOf(value[1]));
zTextView.setText(String.valueOf(value[2]));
//x = Integer.parseInt(value[0]);
//y = Integer.parseInt(value[1]);
//z = Integer.parseInt(value[2]);
LineData data = mChart.getLineData();
if (data != null) {
for (int i = 0; i < 3; i++) {
ILineDataSet set = data.getDataSetByIndex(i);
if (set == null) {
set = createSet(names[i], colors[i]);
data.addDataSet(set);
}
data.addEntry(new Entry(set.getEntryCount(),Float.parseFloat(value[i])), i);
data.notifyDataChanged();
}
mChart.notifyDataSetChanged();
mChart.setVisibleXRangeMaximum(50);
mChart.moveViewToX(data.getEntryCount());
}
}
private LineDataSet createSet(String label, int color) {
LineDataSet set = new LineDataSet(null, label);
set.setLineWidth(2.5f);
set.setColor(color);
set.setDrawCircles(false);
set.setDrawValues(false);
return set;
}
}
package com.example.matu_mio.graphdraw;
import android.app.ActionBar;
import android.app.Activity;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.WindowManager;
import android.widget.TextView;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.Wearable;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
public class MainActivity extends Activity implements GoogleApiClient.ConnectionCallbacks, MessageApi.MessageListener{
private static final String TAG = MainActivity.class.getName();
private GoogleApiClient mGoogleApiClient;
TextView xTextView;
TextView yTextView;
TextView zTextView;
LineChart mChart;
int x,y,z;
String[] names = new String[]{"x-value", "y-value", "z-value"};
int[] colors = new int[]{Color.RED, Color.GREEN, Color.BLUE};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
xTextView = (TextView)findViewById(R.id.xValue);
yTextView = (TextView)findViewById(R.id.yValue);
zTextView = (TextView)findViewById(R.id.zValue);
ActionBar ab = getActionBar();
//ab.hide();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "onConnectionFailed:" + connectionResult.toString());
}
})
.addApi(Wearable.API)
.build();
mChart = (LineChart) findViewById(R.id.lineChart);
mChart.setDescription(null); // 表のタイトルを空にする
mChart.setData(new LineData()); // 空のLineData型インスタンスを追加
}
@Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
@Override
protected void onStop() {
super.onStop();
if (null != mGoogleApiClient && mGoogleApiClient.isConnected()) {
Wearable.MessageApi.removeListener(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
//getMenuInflater().inflate(R.menu.my, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//if (id == R.id.action_settings) {
// return true;
//}
return super.onOptionsItemSelected(item);
}
@Override
public void onConnected(Bundle bundle) {
Log.d(TAG, "onConnected");
Wearable.MessageApi.addListener(mGoogleApiClient, this);
}
@Override
public void onConnectionSuspended(int i) {
Log.d(TAG, "onConnectionSuspended");
}
@Override
public void onMessageReceived(MessageEvent messageEvent) {
xTextView.setText(messageEvent.getPath());
String msg = messageEvent.getPath();
String[] value = msg.split(",", 0);
xTextView.setText(String.valueOf(value[0]));
yTextView.setText(String.valueOf(value[1]));
zTextView.setText(String.valueOf(value[2]));
//x = Integer.parseInt(value[0]);
//y = Integer.parseInt(value[1]);
//z = Integer.parseInt(value[2]);
LineData data = mChart.getLineData();
if (data != null) {
for (int i = 0; i < 3; i++) {
ILineDataSet set = data.getDataSetByIndex(i);
if (set == null) {
set = createSet(names[i], colors[i]);
data.addDataSet(set);
}
data.addEntry(new Entry(set.getEntryCount(),Float.parseFloat(value[i])), i);
data.notifyDataChanged();
}
mChart.notifyDataSetChanged();
mChart.setVisibleXRangeMaximum(50);
mChart.moveViewToX(data.getEntryCount());
}
}
private LineDataSet createSet(String label, int color) {
LineDataSet set = new LineDataSet(null, label);
set.setLineWidth(2.5f);
set.setColor(color);
set.setDrawCircles(false);
set.setDrawValues(false);
return set;
}
}
activity_main.xml(mobile)
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.matu_mio.graphdraw.MainActivity">
<com.github.mikephil.charting.charts.LineChart
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/lineChart"/>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/xValue"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/yValue"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</android.support.constraint.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.matu_mio.graphdraw.MainActivity">
<com.github.mikephil.charting.charts.LineChart
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/lineChart"/>
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/xValue"
android:layout_below="@+id/textView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/yValue"
android:layout_below="@+id/xValue"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/zValue"
android:layout_below="@+id/yValue"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</android.support.constraint.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.matu_mio.graphdraw.MainActivity">
<com.github.mikephil.charting.charts.LineChart
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/lineChart"/>
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/xValue"
android:layout_below="@+id/textView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/yValue"
android:layout_below="@+id/xValue"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/zValue"
android:layout_below="@+id/yValue"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</android.support.constraint.ConstraintLayout>
参考
Android:グラフ表示で表現豊かに。MPAndroidChart を使ってみよう!|マネーフォワード エンジニアブログ
MPAndroidChartを使って「リアルタイム更新のセンサーデータ時系列グラフ」のサンプルを作ってみた|LyricalMaestro0-Qiita
こんにちは。このAndroidWear側のアプリは公開されていますか?
またweb bluetooth apiからその値を取得することはできるものなのでしょうか?
ゆんきちさん
コメントありがとうございます。
こちらのアプリについては公開しておらず、本記事に掲載しているソースコードのみとなっております。
また、Web Bluetooth APIについては本サンプルで使用しておらず、申し訳ございませんが分かりかねます。