Skip to content

Commit c4cf344

Browse files
committed
Update to use new Nearby Messages API from play services 11
1 parent 83ddb73 commit c4cf344

10 files changed

Lines changed: 288 additions & 166 deletions

File tree

app/build.gradle

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
apply plugin: 'com.android.application'
22

33
android {
4-
compileSdkVersion 25
5-
buildToolsVersion "25.0.1"
4+
compileSdkVersion rootProject.ext.compile_sdk_version
5+
buildToolsVersion rootProject.ext.build_tools_version
66
defaultConfig {
77
applicationId "za.co.riggaroo.androidthings.distributedpiano"
88
minSdkVersion 24
9-
targetSdkVersion 25
9+
targetSdkVersion rootProject.ext.target_sdk_version
1010
versionCode 1
1111
versionName "1.0"
1212
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@@ -20,14 +20,14 @@ android {
2020
}
2121

2222
dependencies {
23-
compile fileTree(dir: 'libs', include: ['*.jar'])
24-
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
23+
implementation fileTree(dir: 'libs', include: ['*.jar'])
24+
androidTestImplementation("com.android.support.test.espresso:espresso-core:$espresso_version", {
2525
exclude group: 'com.android.support', module: 'support-annotations'
2626
})
27-
compile 'com.android.support:appcompat-v7:25.1.0'
27+
implementation "com.android.support:appcompat-v7:$support_version"
2828

29-
compile 'com.google.android.things.contrib:driver-pwmspeaker:0.1'
30-
provided 'com.google.android.things:androidthings:0.1-devpreview'
31-
compile 'com.google.android.gms:play-services-nearby:10.0.1'
32-
testCompile 'junit:junit:4.12'
29+
implementation 'com.google.android.things.contrib:driver-pwmspeaker:0.1'
30+
compileOnly "com.google.android.things:androidthings:$things_version"
31+
implementation "com.google.android.gms:play-services-nearby:$play_services_version"
32+
testImplementation "junit:junit:$junit_version"
3333
}

app/src/main/AndroidManifest.xml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
33
package="za.co.riggaroo.androidthings.distributedpiano">
44

5-
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
5+
<!-- Required for Nearby Connections -->
6+
<uses-permission android:name="android.permission.BLUETOOTH" />
7+
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
8+
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
9+
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
10+
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
611

712
<application
813
android:allowBackup="true"
@@ -11,10 +16,6 @@
1116
android:roundIcon="@mipmap/ic_launcher_round"
1217
android:supportsRtl="true"
1318
android:theme="@style/AppTheme">
14-
<meta-data
15-
android:name="com.google.android.gms.nearby.connection.SERVICE_ID"
16-
android:value="@string/service_id" />
17-
1819

1920
<activity android:name=".PianoActivity">
2021
<intent-filter>

app/src/main/java/za/co/riggaroo/androidthings/distributedpiano/PianoActivity.java

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
package za.co.riggaroo.androidthings.distributedpiano;
22

33
import android.app.Activity;
4-
import android.net.ConnectivityManager;
4+
import android.content.pm.PackageManager;
55
import android.os.Bundle;
6+
import android.support.annotation.NonNull;
67
import android.support.annotation.Nullable;
78
import android.util.Log;
89

910
import com.google.android.things.contrib.driver.pwmspeaker.Speaker;
1011

1112
import java.io.IOException;
1213

14+
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
15+
1316
public class PianoActivity extends Activity implements PianoContract.View {
1417

1518
private static final String TAG = "PianoActivity";
19+
private final static int REQUEST_PERMISSION_REQ_CODE = 33;
1620
private Speaker speaker;
1721

1822
private PianoContract.Presenter presenter;
@@ -21,10 +25,44 @@ public class PianoActivity extends Activity implements PianoContract.View {
2125
protected void onCreate(@Nullable final Bundle savedInstanceState) {
2226
super.onCreate(savedInstanceState);
2327

28+
if (hasRequiredPermissions()) {
29+
startComponents();
30+
} else {
31+
requestRequiredPermissions();
32+
}
33+
}
34+
35+
@Override
36+
public void onRequestPermissionsResult(final int requestCode, final @NonNull String[] permissions, final @NonNull int[] grantResults) {
37+
switch (requestCode) {
38+
case REQUEST_PERMISSION_REQ_CODE: {
39+
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
40+
// We have been granted the Manifest.permission.ACCESS_COARSE_LOCATION permission. Now we may proceed with advertising.
41+
startComponents();
42+
presenter.attachView(this);
43+
} else {
44+
Log.w(TAG, "Required permissions not granted");
45+
}
46+
break;
47+
}
48+
}
49+
}
50+
51+
private boolean hasRequiredPermissions() {
52+
return checkSelfPermission(ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
53+
}
54+
55+
private void requestRequiredPermissions() {
56+
if (shouldShowRequestPermissionRationale(ACCESS_COARSE_LOCATION)) {
57+
Log.w(TAG, "Location permission is required for this application");
58+
}
59+
requestPermissions(new String[]{ACCESS_COARSE_LOCATION}, REQUEST_PERMISSION_REQ_CODE);
60+
}
61+
62+
private void startComponents() {
2463
try {
2564
speaker = new Speaker(BoardDefaults.getPwmPin());
26-
presenter = new PianoPresenter(this, (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE),
27-
getString(R.string.service_id), getPackageName());
65+
presenter = new PianoPresenter(this, getString(R.string.service_id));
2866
} catch (IOException e) {
2967
throw new IllegalArgumentException("Piezo can't be opened, lets end this here.");
3068
}
@@ -34,15 +72,17 @@ protected void onCreate(@Nullable final Bundle savedInstanceState) {
3472
public void onStart() {
3573
super.onStart();
3674
Log.d(TAG, "onStart");
37-
presenter.attachView(this);
75+
if (presenter != null)
76+
presenter.attachView(this);
3877

3978
}
4079

4180
@Override
4281
public void onStop() {
4382
super.onStop();
4483
Log.d(TAG, "onStop");
45-
presenter.detachView();
84+
if (presenter != null)
85+
presenter.detachView();
4686

4787
}
4888

app/src/main/java/za/co/riggaroo/androidthings/distributedpiano/PianoPresenter.java

Lines changed: 65 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package za.co.riggaroo.androidthings.distributedpiano;
22

3-
43
import android.content.Context;
5-
import android.net.ConnectivityManager;
6-
import android.net.NetworkInfo;
74
import android.os.Bundle;
85
import android.support.annotation.NonNull;
96
import android.support.annotation.Nullable;
@@ -12,42 +9,91 @@
129
import com.google.android.gms.common.ConnectionResult;
1310
import com.google.android.gms.common.api.GoogleApiClient;
1411
import com.google.android.gms.common.api.ResultCallback;
15-
import com.google.android.gms.common.api.Status;
1612
import com.google.android.gms.nearby.Nearby;
17-
import com.google.android.gms.nearby.connection.AppIdentifier;
18-
import com.google.android.gms.nearby.connection.AppMetadata;
13+
import com.google.android.gms.nearby.connection.AdvertisingOptions;
14+
import com.google.android.gms.nearby.connection.ConnectionInfo;
15+
import com.google.android.gms.nearby.connection.ConnectionLifecycleCallback;
16+
import com.google.android.gms.nearby.connection.ConnectionResolution;
1917
import com.google.android.gms.nearby.connection.Connections;
2018
import com.google.android.gms.nearby.connection.ConnectionsStatusCodes;
19+
import com.google.android.gms.nearby.connection.Payload;
20+
import com.google.android.gms.nearby.connection.PayloadCallback;
21+
import com.google.android.gms.nearby.connection.PayloadTransferUpdate;
22+
import com.google.android.gms.nearby.connection.Strategy;
2123

2224
import java.io.IOException;
2325
import java.nio.ByteBuffer;
24-
import java.util.ArrayList;
25-
import java.util.List;
2626

2727
class PianoPresenter implements PianoContract.Presenter, GoogleApiClient.ConnectionCallbacks,
28-
GoogleApiClient.OnConnectionFailedListener, Connections.ConnectionRequestListener, Connections.MessageListener {
28+
GoogleApiClient.OnConnectionFailedListener {
2929

3030
private static final String TAG = "PianoPresenter";
3131
private final GoogleApiClient googleApiClient;
32+
private static final String DEVICE_NAME = "DistributedPiano";
3233
private final String serviceId;
33-
private final String packageName;
3434
private PianoContract.View view;
35-
private ConnectivityManager connectivityManager;
3635

37-
PianoPresenter(Context context, ConnectivityManager connectivityManager, String serviceId,
38-
String packageName) throws IOException {
36+
private final ConnectionLifecycleCallback connectionLifecycleCallback = new ConnectionLifecycleCallback() {
37+
@Override
38+
public void onConnectionInitiated(String endpointId, ConnectionInfo connectionInfo) {
39+
Log.d(TAG, "Connection initiated from " + endpointId + " " + connectionInfo.getEndpointName());
40+
Nearby.Connections.acceptConnection(googleApiClient, endpointId, payloadCallback);
41+
}
42+
43+
@Override
44+
public void onConnectionResult(String endpointId, ConnectionResolution connectionResolution) {
45+
Log.d(TAG, "onConnectionResult");
46+
if (connectionResolution.getStatus().isSuccess()) {
47+
Log.d(TAG, "Endpoint " + endpointId + " connected");
48+
} else {
49+
Log.w(TAG, "Endpoint " + endpointId + " already connected");
50+
}
51+
}
52+
53+
@Override
54+
public void onDisconnected(String endpointId) {
55+
Log.d(TAG, endpointId + " disconnected");
56+
}
57+
};
58+
59+
private final PayloadCallback payloadCallback = new PayloadCallback() {
60+
@Override
61+
public void onPayloadReceived(String endpointId, Payload payload) {
62+
Log.d(TAG, "onPayloadReceived");
63+
double frequency = toDouble(payload.asBytes());
64+
if (frequency == -1) {
65+
view.stopPlayingNote();
66+
return;
67+
}
68+
view.playNote(frequency);
69+
}
70+
71+
@Override
72+
public void onPayloadTransferUpdate(String endpointId, PayloadTransferUpdate payloadTransferUpdate) {
73+
switch (payloadTransferUpdate.getStatus()) {
74+
case PayloadTransferUpdate.Status.IN_PROGRESS:
75+
Log.d(TAG, "onPayloadTransferUpdate " + payloadTransferUpdate.getBytesTransferred() + " bytes transferred");
76+
break;
77+
case PayloadTransferUpdate.Status.SUCCESS:
78+
Log.d(TAG, "onPayloadTransferUpdate completed");
79+
break;
80+
case PayloadTransferUpdate.Status.FAILURE:
81+
Log.d(TAG, "onPayloadTransferUpdate failed");
82+
break;
83+
}
84+
}
85+
};
86+
87+
PianoPresenter(Context context, String serviceId) throws IOException {
3988
googleApiClient = new GoogleApiClient.Builder(context).addConnectionCallbacks(this)
4089
.addOnConnectionFailedListener(this).addApi(Nearby.CONNECTIONS_API).build();
4190
this.serviceId = serviceId;
42-
this.connectivityManager = connectivityManager;
43-
this.packageName = packageName;
4491
}
4592

4693
@Override
4794
public void onConnected(@Nullable final Bundle bundle) {
4895
Log.d(TAG, "onConnected!");
4996
startAdvertising();
50-
5197
}
5298

5399
@Override
@@ -60,25 +106,11 @@ public void onConnectionFailed(@NonNull final ConnectionResult connectionResult)
60106
Log.d(TAG, "onConnectionFailed");
61107
}
62108

63-
private boolean isConnectedToNetwork() {
64-
NetworkInfo info = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
65-
NetworkInfo info1 = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_ETHERNET);
66-
67-
return (info != null && info.isConnectedOrConnecting()) || (info1 != null && info1.isConnectedOrConnecting());
68-
}
69-
70-
71109
private void startAdvertising() {
72110
Log.d(TAG, "startAdvertising");
73-
if (!isConnectedToNetwork()) {
74-
Log.d(TAG, "startAdvertising: not connected to WiFi network.");
75-
return;
76-
}
77-
78-
List<AppIdentifier> appIdentifierList = new ArrayList<>();
79-
appIdentifierList.add(new AppIdentifier(packageName));
80-
AppMetadata appMetadata = new AppMetadata(appIdentifierList);
81-
Nearby.Connections.startAdvertising(googleApiClient, serviceId, appMetadata, 0L, this)
111+
AdvertisingOptions advertisingOptions = new AdvertisingOptions(Strategy.P2P_CLUSTER);
112+
Nearby.Connections
113+
.startAdvertising(googleApiClient, DEVICE_NAME, serviceId, connectionLifecycleCallback, advertisingOptions)
82114
.setResultCallback(new ResultCallback<Connections.StartAdvertisingResult>() {
83115
@Override
84116
public void onResult(@NonNull Connections.StartAdvertisingResult result) {
@@ -99,44 +131,10 @@ public void onResult(@NonNull Connections.StartAdvertisingResult result) {
99131
});
100132
}
101133

102-
@Override
103-
public void onConnectionRequest(final String endpointId, String deviceId, String endpointName, byte[] payload) {
104-
Log.d(TAG, "onConnectionRequest");
105-
106-
Nearby.Connections.acceptConnectionRequest(googleApiClient, endpointId, payload, this)
107-
.setResultCallback(new ResultCallback<Status>() {
108-
@Override
109-
public void onResult(@NonNull Status status) {
110-
if (status.isSuccess()) {
111-
Log.d(TAG, "acceptConnectionRequest: SUCCESS");
112-
113-
} else {
114-
Log.d(TAG, "acceptConnectionRequest: FAILURE");
115-
}
116-
}
117-
});
118-
}
119-
120-
@Override
121-
public void onMessageReceived(final String s, final byte[] bytes, final boolean b) {
122-
Log.d(TAG, "onMessageReceived");
123-
double frequency = toDouble(bytes);
124-
if (frequency == -1) {
125-
view.stopPlayingNote();
126-
return;
127-
}
128-
view.playNote(frequency);
129-
}
130-
131134
private static double toDouble(byte[] bytes) {
132135
return ByteBuffer.wrap(bytes).getDouble();
133136
}
134137

135-
@Override
136-
public void onDisconnected(final String s) {
137-
138-
}
139-
140138
@Override
141139
public void detachView() {
142140
this.view = null;

build.gradle

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
buildscript {
44
repositories {
55
jcenter()
6+
maven { url 'https://maven.google.com' }
67
}
78
dependencies {
8-
classpath 'com.android.tools.build:gradle:2.3.0-beta2'
9+
classpath 'com.android.tools.build:gradle:3.0.0-alpha4'
910

1011
// NOTE: Do not place your application dependencies here; they belong
1112
// in the individual module build.gradle files
@@ -15,9 +16,19 @@ buildscript {
1516
allprojects {
1617
repositories {
1718
jcenter()
19+
maven { url 'https://maven.google.com' }
1820
}
1921
}
2022

2123
task clean(type: Delete) {
2224
delete rootProject.buildDir
2325
}
26+
27+
ext.compile_sdk_version = 26
28+
ext.build_tools_version = "26.0.0"
29+
ext.target_sdk_version = 26
30+
ext.support_version = "26.0.0-beta2"
31+
ext.play_services_version = "11.0.1"
32+
ext.things_version = "0.4.1-devpreview"
33+
ext.junit_version = "4.12"
34+
ext.espresso_version = "2.2.2"
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#Sun Jan 22 17:32:18 SAST 2017
1+
#Mon Jun 19 08:39:43 BST 2017
22
distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-rc-1-all.zip

0 commit comments

Comments
 (0)