我尝试为Googles Nearby Connections API实现一个小型测试应用程序。不幸的是,在3个经过测试的设备中,有2个Google Play服务在发现或广告时会崩溃。 (OnePlus One,Android 6.1; Acer Iconia,Android 4.4)
我看到其他设备,但是当我连接到其中一个设备时发生服务崩溃(只有我的Honor 8继续工作)。它表示连接与错误代码1一致。根据Google,这意味着“暂停原因通知服务已被杀死”。
也许有些人可以提供帮助。我根据this教程制作了这段代码。 没有进口的代码:
MainActivity.java
package com.example.steffen.nearbyconnectionsdemo;
public class MainActivity extends Activity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
View.OnClickListener,
Connections.ConnectionRequestListener,
Connections.MessageListener,
Connections.EndpointDiscoveryListener {
// Identify if the device is the host
private boolean mIsHost = false;
GoogleApiClient mGoogleApiClient = null;
Button bt_ad, bt_search, bt_send;
TextView tv_status;
CheckBox checkBox;
Context c;
String globalRemoteEndpointId = "";
EditText editText;
final int MY_PERMISSIONS_REQUEST = 666;
private static int[] NETWORK_TYPES = {ConnectivityManager.TYPE_WIFI,
ConnectivityManager.TYPE_ETHERNET};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
c = this;
checkPermisson();
editText = (EditText) findViewById(R.id.editText);
bt_ad = (Button) findViewById(R.id.bt_ad);
bt_ad.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
bt_search.setEnabled(false);
startAdvertising();
}
});
bt_search = (Button) findViewById(R.id.bt_search);
bt_search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startDiscovery();
}
});
bt_send = (Button) findViewById(R.id.bt_send);
bt_send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String message = "message: " + editText.getText().toString();
Toast.makeText(c, "Sending: " + message, Toast.LENGTH_SHORT).show();
byte[] payload = message.getBytes();
Nearby.Connections.sendReliableMessage(mGoogleApiClient, globalRemoteEndpointId, payload);
}
});
tv_status = (TextView) findViewById(R.id.tv_status);
checkBox = (CheckBox) findViewById(R.id.checkBox);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Nearby.CONNECTIONS_API)
.build();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
private boolean isConnectedToNetwork() {
ConnectivityManager connManager =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
for (int networkType : NETWORK_TYPES) {
NetworkInfo info = connManager.getNetworkInfo(networkType);
if (info != null && info.isConnectedOrConnecting()) {
return true;
}
}
return false;
}
private void startAdvertising() {
if (!isConnectedToNetwork()) {
// Implement logic when device is not connected to a network
tv_status.setText("No Network");
return;
}
// Identify that this device is the host
mIsHost = true;
checkBox.setChecked(mIsHost);
// Advertising with an AppIdentifer lets other devices on the
// network discover this application and prompt the user to
// install the application.
List<AppIdentifier> appIdentifierList = new ArrayList<>();
appIdentifierList.add(new AppIdentifier(getPackageName()));
AppMetadata appMetadata = new AppMetadata(appIdentifierList);
// The advertising timeout is set to run indefinitely
// Positive values represent timeout in milliseconds
long NO_TIMEOUT = 0L;
String name = null;
Nearby.Connections.startAdvertising(mGoogleApiClient, name, appMetadata, NO_TIMEOUT,
this).setResultCallback(new ResultCallback<Connections.StartAdvertisingResult>() {
@Override
public void onResult(Connections.StartAdvertisingResult result) {
if (result.getStatus().isSuccess()) {
// Device is advertising
tv_status.setText("Advertising");
} else {
int statusCode = result.getStatus().getStatusCode();
// Advertising failed - see statusCode for more details
tv_status.setText("Error: " + statusCode);
}
}
});
}
private void startDiscovery() {
if (!isConnectedToNetwork()) {
// Implement logic when device is not connected to a network
tv_status.setText("No Network");
return;
}
String serviceId = getString(R.string.service_id);
// Set an appropriate timeout length in milliseconds
long DISCOVER_TIMEOUT = 1000L;
// Discover nearby apps that are advertising with the required service ID.
Nearby.Connections.startDiscovery(mGoogleApiClient, serviceId, DISCOVER_TIMEOUT, this)
.setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
if (status.isSuccess()) {
// Device is discovering
tv_status.setText("Discovering");
} else {
int statusCode = status.getStatusCode();
// Advertising failed - see statusCode for more details
tv_status.setText("Error: " + statusCode);
}
}
});
}
@Override
public void onEndpointFound(final String endpointId, String deviceId,
String serviceId, final String endpointName) {
// This device is discovering endpoints and has located an advertiser.
// Write your logic to initiate a connection with the device at
// the endpoint ID
Toast.makeText(this, "Found Device: " + serviceId + ", " + endpointName + ". Start Connection Try", Toast.LENGTH_SHORT).show();
connectTo(endpointId, endpointName);
}
private void connectTo(String remoteEndpointId, final String endpointName) {
// Send a connection request to a remote endpoint. By passing 'null' for
// the name, the Nearby Connections API will construct a default name
// based on device model such as 'LGE Nexus 5'.
tv_status.setText("Connecting");
String myName = null;
byte[] myPayload = null;
Nearby.Connections.sendConnectionRequest(mGoogleApiClient, myName,
remoteEndpointId, myPayload, new Connections.ConnectionResponseCallback() {
@Override
public void onConnectionResponse(String remoteEndpointId, Status status,
byte[] bytes) {
if (status.isSuccess()) {
// Successful connection
tv_status.setText("Connected to " + endpointName);
globalRemoteEndpointId = remoteEndpointId;
} else {
// Failed connection
tv_status.setText("Connecting failed");
}
}
}, this);
}
@Override
public void onConnectionRequest(final String remoteEndpointId, String remoteDeviceId,
final String remoteEndpointName, byte[] payload) {
if (mIsHost) {
byte[] myPayload = null;
// Automatically accept all requests
Nearby.Connections.acceptConnectionRequest(mGoogleApiClient, remoteEndpointId,
myPayload, this).setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
if (status.isSuccess()) {
String statusS = "Connected to " + remoteEndpointName;
Toast.makeText(c, statusS,
Toast.LENGTH_SHORT).show();
tv_status.setText(statusS);
globalRemoteEndpointId = remoteEndpointId;
} else {
String statusS = "Failed to connect to: " + remoteEndpointName;
Toast.makeText(c, statusS,
Toast.LENGTH_SHORT).show();
tv_status.setText(statusS);
}
}
});
} else {
// Clients should not be advertising and will reject all connection requests.
Nearby.Connections.rejectConnectionRequest(mGoogleApiClient, remoteEndpointId);
}
}
@Override
public void onMessageReceived(String endpointId, byte[] payload, boolean b) {
String message = payload.toString();
Toast.makeText(this, "Received from " + endpointId + ": " + message, Toast.LENGTH_SHORT).show();
}
@Override
public void onClick(View view) {
}
@Override
public void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
@Override
public void onStop() {
super.onStop();
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
@Override
public void onConnected(Bundle bundle) {
}
@Override
public void onConnectionSuspended(int i) {
tv_status.setText("Connection suspended because of " + i);
mGoogleApiClient.reconnect();
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
tv_status.setText("Connection Failed");
}
@Override
public void onEndpointLost(String s) {
tv_status.setText("Endpoint lost: " + s);
}
@Override
public void onDisconnected(String s) {
tv_status.setText("Disconnected: " + s);
}
public void checkPermisson(){
Toast.makeText(c, "Check permission", Toast.LENGTH_SHORT).show();
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_NETWORK_STATE}, MY_PERMISSIONS_REQUEST);
}
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST:
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
Toast.makeText(c, "Permission granted", Toast.LENGTH_SHORT).show();
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(c, "Permission not granted, app may fail", Toast.LENGTH_SHORT).show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}