package com.tutsplus.nearbymessages;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Spinner;
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.common.api.Status;
import com.google.android.gms.nearby.Nearby;
import com.google.android.gms.nearby.connection.Connections;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
Connections.ConnectionRequestListener,
Connections.MessageListener,
Connections.EndpointDiscoveryListener,
View.OnClickListener {
private GoogleApiClient mGoogleApiClient;
private Spinner mTypeSpinner;
private TextView mStatusText;
private Button mConnectionButton;
private Button mSendButton;
private ListView mListView;
private ViewGroup mSendTextContainer;
private EditText mSendEditText;
private ArrayAdapter<String> mMessageAdapter;
private boolean mIsHost;
private boolean mIsConnected;
private String mRemoteHostEndpoint;
private List<String> mRemotePeerEndpoints = new ArrayList<String>();
private static final long CONNECTION_TIME_OUT = 10000L;
//Wifi or Ethernet for TVs
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);
initViews();
}
@Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
@Override
protected void onStop() {
super.onStop();
if( mGoogleApiClient != null && mGoogleApiClient.isConnected() ) {
Nearby.Connections.stopAdvertising(mGoogleApiClient);
mGoogleApiClient.disconnect();
}
}
private void initViews() {
mStatusText = (TextView) findViewById( R.id.text_status );
mConnectionButton = (Button) findViewById( R.id.button_connection );
mSendButton = (Button) findViewById( R.id.button_send );
mListView = (ListView) findViewById( R.id.list );
mSendTextContainer = (ViewGroup) findViewById( R.id.send_text_container );
mSendEditText = (EditText) findViewById( R.id.edit_text_send );
mTypeSpinner = (Spinner) findViewById( R.id.spinner_type );
setupButtons();
setupConnectionTypeSpinner();
setupMessageList();
mGoogleApiClient = new GoogleApiClient.Builder( this )
.addConnectionCallbacks( this )
.addOnConnectionFailedListener( this )
.addApi( Nearby.CONNECTIONS_API )
.build();
}
private void setupButtons() {
mConnectionButton.setOnClickListener(this);
mSendButton.setOnClickListener(this);
}
private void setupConnectionTypeSpinner() {
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
this,
R.array.connection_types,
android.R.layout.simple_spinner_item );
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mTypeSpinner.setAdapter(adapter);
}
private void setupMessageList() {
mMessageAdapter = new ArrayAdapter<String>( this, android.R.layout.simple_list_item_1 );
mListView.setAdapter( mMessageAdapter );
}
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 disconnect() {
if( !isConnectedToNetwork() )
return;
if( mIsHost ) {
sendMessage( "Shutting down host" );
Nearby.Connections.stopAdvertising( mGoogleApiClient );
Nearby.Connections.stopAllEndpoints( mGoogleApiClient );
mIsHost = false;
mStatusText.setText( "Not connected" );
mRemotePeerEndpoints.clear();
} else {
if( !mIsConnected || TextUtils.isEmpty( mRemoteHostEndpoint ) ) {
Nearby.Connections.stopDiscovery( mGoogleApiClient, getString( R.string.service_id ) );
return;
}
sendMessage( "Disconnecting" );
Nearby.Connections.disconnectFromEndpoint( mGoogleApiClient, mRemoteHostEndpoint );
mRemoteHostEndpoint = null;
mStatusText.setText( "Disconnected" );
}
mIsConnected = false;
}
private void advertise() {
if( !isConnectedToNetwork() )
return;
String name = "Nearby Advertising";
Nearby.Connections.startAdvertising( mGoogleApiClient, name, null, CONNECTION_TIME_OUT, this ).setResultCallback(new ResultCallback<Connections.StartAdvertisingResult>() {
@Override
public void onResult(Connections.StartAdvertisingResult result) {
if (result.getStatus().isSuccess()) {
mStatusText.setText("Advertising");
}
}
});
}
private void discover() {
if( !isConnectedToNetwork() )
return;
String serviceId = getString( R.string.service_id );
Nearby.Connections.startDiscovery(mGoogleApiClient, serviceId, 10000L, this).setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
if (status.isSuccess()) {
mStatusText.setText( "Discovering" );
}
}
});
}
@Override
public void onConnected(Bundle bundle) {
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionRequest(final String remoteEndpointId, final String remoteDeviceId, final String remoteEndpointName, byte[] payload) {
if( mIsHost ) {
Nearby.Connections.acceptConnectionRequest( mGoogleApiClient, remoteEndpointId, payload, this ).setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status status) {
if( status.isSuccess() ) {
if( !mRemotePeerEndpoints.contains( remoteEndpointId ) ) {
mRemotePeerEndpoints.add( remoteEndpointId );
}
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mMessageAdapter.notifyDataSetChanged();
sendMessage(remoteDeviceId + " connected!");
mSendTextContainer.setVisibility( View.VISIBLE );
}
}
});
} else {
Nearby.Connections.rejectConnectionRequest(mGoogleApiClient, remoteEndpointId );
}
}
private void sendMessage( String message ) {
if( mIsHost ) {
Nearby.Connections.sendReliableMessage(mGoogleApiClient, mRemotePeerEndpoints, message.getBytes());
mMessageAdapter.add(message);
mMessageAdapter.notifyDataSetChanged();
} else {
Nearby.Connections.sendReliableMessage( mGoogleApiClient, mRemoteHostEndpoint, ( Nearby.Connections.getLocalDeviceId( mGoogleApiClient ) + " says: " + message ).getBytes() );
}
}
@Override
public void onEndpointFound(String endpointId, String deviceId, final String serviceId, String endpointName) {
byte[] payload = null;
Nearby.Connections.sendConnectionRequest( mGoogleApiClient, deviceId, endpointId, payload, new Connections.ConnectionResponseCallback() {
@Override
public void onConnectionResponse(String s, Status status, byte[] bytes) {
if( status.isSuccess() ) {
mStatusText.setText( "Connected to: " + s );
Nearby.Connections.stopDiscovery(mGoogleApiClient, serviceId);
mRemoteHostEndpoint = s;
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mSendTextContainer.setVisibility(View.VISIBLE);
if( !mIsHost ) {
mIsConnected = true;
}
} else {
mStatusText.setText( "Connection to " + s + " failed" );
if( !mIsHost ) {
mIsConnected = false;
}
}
}
}, this );
}
@Override
public void onEndpointLost(String s) {
if( !mIsHost ) {
mIsConnected = false;
}
}
@Override
public void onMessageReceived(String endpointId, byte[] payload, boolean isReliable) {
mMessageAdapter.add( new String( payload ) );
mMessageAdapter.notifyDataSetChanged();
if( mIsHost ) {
sendMessage( new String( payload ) );
}
}
@Override
public void onDisconnected(String s) {
if( !mIsHost ) {
mIsConnected = false;
}
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
if( !mIsHost ) {
mIsConnected = false;
}
}
@Override
public void onClick(View v) {
switch( v.getId() ) {
case R.id.button_connection: {
if( mIsConnected ) {
disconnect();
mStatusText.setText("Disconnected");
} else if( getString( R.string.connection_type_host ).equalsIgnoreCase( mTypeSpinner.getSelectedItem().toString() ) ) {
mIsHost = true;
advertise();
} else {
mIsHost = false;
discover();
}
break;
}
case R.id.button_send: {
if( !TextUtils.isEmpty( mSendEditText.getText() ) && mIsConnected || ( mRemotePeerEndpoints != null && !mRemotePeerEndpoints.isEmpty() ) ) {
sendMessage( mSendEditText.getText().toString() );
mSendEditText.setText( "" );
}
break;
}
}
}
}