0

I try to implement a small test application for Googles Nearby Connections API. Unfortunately on 2 of 3 tested devices Google Play Services chrash when discovering or advertising. (OnePlus One, Android 6.1; Acer Iconia, Android 4.4)

I see other devices, but when i connect to one of them play service crash (only my Honor 8 keeps on working). It says the connection is suspendend with error code 1. According to Google this means "A suspension cause informing that the service has been killed."

Maybe some of you could help. I made this code based on this tutorial. Code without imports:

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);

        }
    }
}
SteffenH
  • 97
  • 3
  • 12
  • 2
    Can we see crash log, so we can get more idea about crash cause. – pRaNaY Feb 20 '17 at 19:38
  • I found no way to send the complete crash report, but i made screenshot of the parts which i think could be imortant: [Pic1](https://t74i.imgup.net/96ff8082-32d82.jpg) [Pic2](https://r82i.imgup.net/b13bf4b5-3dc7b.jpg). On the Acer there is no option to see details in crashing dialog. – SteffenH Feb 20 '17 at 19:54
  • The logcat would be helpful. Check and see if this is related to your issue - "Google Play Services" dialog has crashed after discovery timeout: https://code.google.com/p/android/issues/detail?can=1&start=0&num=100&q=nearby%20connections%20nullpointerexception&colspec=ID%20Status%20Priority%20Owner%20Summary%20Stars%20Reporter%20Opened&groupby=&sort=&id=316748 – Chad Schultz Apr 08 '17 at 20:49

0 Answers0