package com.luciofm.droidcon.ifican.activity;
import android.app.Activity;
import android.app.ActivityOptions;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.net.DhcpInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.StrictMode;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryonet.Client;
import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Listener;
import com.esotericsoftware.kryonet.Server;
import com.google.gson.Gson;
import com.luciofm.droidcon.ifican.IfICan;
import com.luciofm.droidcon.ifican.R;
import com.luciofm.droidcon.ifican.bluetooth.BluetoothChatService;
import com.luciofm.droidcon.ifican.model.PresenterMessage;
import com.luciofm.droidcon.ifican.util.MessageEvent;
import com.luciofm.droidcon.ifican.util.RemoteEvent;
import com.squareup.otto.Subscribe;
import java.io.IOException;
import butterknife.ButterKnife;
import butterknife.InjectView;
import butterknife.OnClick;
public class StartActivity extends Activity {
private static final String TAG = "MainActivity";
private BluetoothAdapter mBluetoothAdapter;
private BluetoothChatService mChatService;
private static final long DISCOVERABLE_DELAY = 60000;
Handler handler = new Handler();
private Client mClient;
private Connection mConnection;
@InjectView(R.id.input_ip)
EditText inputIp;
@InjectView(R.id.button_connect)
Button buttonConnect;
@InjectView(R.id.button_start)
View button_start;
private WifiManager wifi;
private DhcpInfo dhcpInfo;
@Override
public void onStart() {
super.onStart();
Log.d(TAG, "++ ON START ++");
// If BT is not on, request that it be enabled.
// setupChat() will then be called during onActivityResult
if (mBluetoothAdapter != null && !mBluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, BluetoothChatService.REQUEST_ENABLE_BT);
// Otherwise, setup the chat session
} else {
if (mChatService == null) setupChat();
}
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
mClient = new Client();
Kryo kryo = mClient.getKryo();
kryo.register(PresenterMessage.class);
mClient.start();
mClient.addListener(new Listener() {
@Override
public void connected(Connection connection) {
super.connected(connection);
mConnection = connection;
Log.d(TAG, "Connected: TCP");
sendTcpConnectedMessage();
buttonStartClick(button_start);
}
@Override
public void received(Connection connection, Object object) {
super.received(connection, object);
if (object instanceof PresenterMessage)
parseTcpMessage((PresenterMessage) object);
}
});
wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
dhcpInfo = wifi.getDhcpInfo();
inputIp.setText(intToIp(dhcpInfo.gateway));
}
public String intToIp(int i) {
return ((i >> 24 ) & 0xFF ) + "." +
((i >> 16 ) & 0xFF) + "." +
((i >> 8 ) & 0xFF) + "." +
( i & 0xFF) ;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
ButterKnife.inject(this);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// If the adapter is null, then Bluetooth is not supported
if (mBluetoothAdapter == null) {
Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
return;
}
//handler.postDelayed(checkDiscoverableRunner, DISCOVERABLE_DELAY);
IfICan.getBusInstance().register(this);
}
private void ensureDiscoverable() {
Log.d(TAG, "ensure discoverable");
if (mBluetoothAdapter.getScanMode() !=
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
makeDiscoverable();
}
}
private void makeDiscoverable() {
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
}
@Override
public synchronized void onResume() {
super.onResume();
Log.d(TAG, "+ ON RESUME +");
// Performing this check in onResume() covers the case in which BT was
// not enabled during onStart(), so we were paused to enable it...
// onResume() will be called when ACTION_REQUEST_ENABLE activity returns.
if (mBluetoothAdapter != null && mChatService != null) {
// Only if the state is STATE_NONE, do we know that we haven't started already
if (mChatService.getState() == BluetoothChatService.STATE_NONE) {
// Start the Bluetooth chat services
mChatService.start();
}
}
}
@Override
public synchronized void onPause() {
super.onPause();
Log.d(TAG, "- ON PAUSE -");
}
@Override
public void onStop() {
super.onStop();
Log.d(TAG, "-- ON STOP --");
}
@Override
public void onDestroy() {
super.onDestroy();
// Stop the Bluetooth chat services
if (mChatService != null) mChatService.stop();
handler.removeCallbacks(checkDiscoverableRunner);
Log.d(TAG, "--- ON DESTROY ---");
IfICan.getBusInstance().unregister(this);
}
private void setupChat() {
Log.d(TAG, "setupChat()");
// Initialize the BluetoothChatService to perform bluetooth connections
mChatService = new BluetoothChatService(this, mHandler);
}
private String mConnectedDeviceName;
// The Handler that gets information back from the BluetoothChatService
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BluetoothChatService.MESSAGE_STATE_CHANGE:
Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
switch (msg.arg1) {
case BluetoothChatService.STATE_CONNECTED:
Log.d(TAG, "Connected: " + mConnectedDeviceName);
sendConnectedMessage();
buttonStartClick(button_start);
//handler.postDelayed(checkDiscoverableRunner, DISCOVERABLE_DELAY);
break;
case BluetoothChatService.STATE_CONNECTING:
Log.d(TAG, "Connecting");
break;
case BluetoothChatService.STATE_LISTEN:
case BluetoothChatService.STATE_NONE:
Log.d(TAG, "Idle");
//ensureDiscoverable();
break;
}
break;
case BluetoothChatService.MESSAGE_WRITE:
byte[] writeBuf = (byte[]) msg.obj;
// construct a string from the buffer
String writeMessage = new String(writeBuf);
Log.d(TAG, "sent: " + writeMessage);
break;
case BluetoothChatService.MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
Log.d(TAG, "recvd: " + readMessage);
parseMessage(readMessage);
break;
case BluetoothChatService.MESSAGE_DEVICE_NAME:
// save the connected device's name
mConnectedDeviceName = msg.getData().getString(BluetoothChatService.DEVICE_NAME);
Log.d(TAG, "DEVICE: " + mConnectedDeviceName);
break;
case BluetoothChatService.MESSAGE_TOAST:
Toast.makeText(getApplicationContext(), msg.getData().getString(BluetoothChatService.TOAST),
Toast.LENGTH_SHORT).show();
break;
}
}
};
private void sendConnectedMessage() {
Gson gson = new Gson();
mChatService.write(gson.toJson(new PresenterMessage("text", "Connected..."),
PresenterMessage.class).getBytes());
}
private void parseMessage(String message) {
Gson gson = new Gson();
PresenterMessage msg = gson.fromJson(message, PresenterMessage.class);
String method = msg.getMethod();
if (method.contentEquals("ping"))
mChatService.write(pongMessage());
else if (method.contentEquals("pong"))
Toast.makeText(this, "PONG", Toast.LENGTH_SHORT).show();
else {
postCommand(method);
}
}
private void postCommand(String method) {
RemoteEvent event = null;
if (method.contentEquals("prev"))
event = new RemoteEvent(RemoteEvent.EVENT_PREV);
else if (method.contentEquals("next"))
event = new RemoteEvent(RemoteEvent.EVENT_NEXT);
else if (method.contentEquals("back"))
event = new RemoteEvent(RemoteEvent.EVENT_BACK);
else if (method.contentEquals("advance"))
event = new RemoteEvent(RemoteEvent.EVENT_ADVANCE);
IfICan.getBusInstance().post(event);
}
private byte[] pongMessage() {
Gson gson = new Gson();
return gson.toJson(new PresenterMessage("pong"), PresenterMessage.class).getBytes();
}
private byte[] pingMessage() {
Gson gson = new Gson();
return gson.toJson(new PresenterMessage("ping"), PresenterMessage.class).getBytes();
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult " + resultCode);
switch (requestCode) {
case BluetoothChatService.REQUEST_ENABLE_BT:
// When the request to enable Bluetooth returns
if (resultCode == Activity.RESULT_OK) {
// Bluetooth is now enabled, so set up a chat session
setupChat();
} else {
// User did not enable Bluetooth or an error occurred
Log.d(TAG, "BT not enabled");
Toast.makeText(this, "Bluetooth not enabled, leaving...", Toast.LENGTH_SHORT).show();
finish();
}
}
}
Runnable checkDiscoverableRunner = new Runnable() {
@Override
public void run() {
if (mChatService.getState() == BluetoothChatService.STATE_LISTEN ||
mChatService.getState() == BluetoothChatService.STATE_NONE) {
ensureDiscoverable();
}
handler.postDelayed(this, DISCOVERABLE_DELAY);
}
};
@OnClick(R.id.button_start)
public void buttonStartClick(View view) {
Intent intent = new Intent(this, MainActivity.class);
ActivityOptions options = ActivityOptions.makeScaleUpAnimation(view, 0, 0,
view.getWidth(), view.getHeight());
startActivity(intent, options.toBundle());
handler.removeCallbacks(checkDiscoverableRunner);
}
@OnClick(R.id.button_connect)
public void onConnectClicked() {
try {
mClient.connect(15, inputIp.getText().toString(), 8080);
} catch (IOException e) {
e.printStackTrace();
}
}
@Subscribe
public void onMessageEvent(MessageEvent event) {
sendMessage(event.getMessage());
}
private void sendMessage(String message) {
Gson gson = new Gson();
mChatService.write(gson.toJson(new PresenterMessage("text", message),
PresenterMessage.class).getBytes());
}
private void sendTcpConnectedMessage() {
if (mConnection != null)
mConnection.sendTCP(new PresenterMessage("text", "Connected..."));
}
private void parseTcpMessage(PresenterMessage msg) {
Gson gson = new Gson();
String method = msg.getMethod();
if (method.contentEquals("ping"))
pongTcpMessage();
else if (method.contentEquals("pong"))
Toast.makeText(this, "PONG", Toast.LENGTH_SHORT).show();
else {
postCommand(method);
}
}
private void pongTcpMessage() {
if (mConnection != null)
mConnection.sendTCP(new PresenterMessage("pong"));
}
}