123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601 |
- package de.tudarmstadt.informatik.hostage.sync.p2p;
- import android.app.Activity;
- import android.app.ProgressDialog;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.IntentFilter;
- import android.net.wifi.p2p.WifiP2pConfig;
- import android.net.wifi.p2p.WifiP2pDevice;
- import android.net.wifi.p2p.WifiP2pDeviceList;
- import android.net.wifi.p2p.WifiP2pGroup;
- import android.net.wifi.p2p.WifiP2pInfo;
- import android.net.wifi.p2p.WifiP2pManager;
- import android.os.AsyncTask;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.AdapterView;
- import android.widget.ArrayAdapter;
- import android.widget.ListView;
- import android.widget.RelativeLayout;
- import android.widget.TextView;
- import android.widget.Toast;
- import android.widget.ViewAnimator;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.ObjectInputStream;
- import java.io.ObjectOutputStream;
- import java.io.OutputStream;
- import java.io.Reader;
- import java.io.UnsupportedEncodingException;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import java.net.InetSocketAddress;
- import java.net.ServerSocket;
- import java.net.Socket;
- import java.util.ArrayList;
- import java.util.List;
- import de.tudarmstadt.informatik.hostage.R;
- import de.tudarmstadt.informatik.hostage.logging.Record;
- import de.tudarmstadt.informatik.hostage.logging.SyncData;
- import de.tudarmstadt.informatik.hostage.logging.SyncInfo;
- import de.tudarmstadt.informatik.hostage.persistence.HostageDBOpenHelper;
- import de.tudarmstadt.informatik.hostage.sync.Synchronizer;
- import de.tudarmstadt.informatik.hostage.ui.activity.MainActivity;
- public class P2PSyncActivity extends Activity implements WifiP2pManager.GroupInfoListener, WifiP2pManager.PeerListListener, WifiP2pManager.ChannelListener, AdapterView.OnItemClickListener, WifiP2pManager.ConnectionInfoListener {
- private WifiP2pManager mManager;
- private WifiP2pManager.Channel mChannel;
- private BroadcastReceiver mReceiver;
- private IntentFilter mIntentFilter;
- private List<WifiP2pDevice> peers = new ArrayList<WifiP2pDevice>();
- private TextView mTxtP2PDeviceName;
- private TextView mTxtP2PDeviceStatus;
- private ViewAnimator mViewAnimator;
- private RelativeLayout mDevicesContainer;
- private TextView mTxtP2PSearchProgress;
- private ListView mLstP2PDevices;
- private RelativeLayout mWelcomeContainer;
- private TextView mTxtP2PNotAvailable;
- private TextView mTxtP2PChangeDeviceName;
- private WifiP2pDevice mDevice;
- private WifiP2pDevice mOtherDevice;
- private WifiP2pInfo mInfo;
- private final int OWNER_SERVER_PORT = 8988;
- private final int CLIENT_SERVER_PORT = 8989;
- private ClientAsyncTask clientAsync;
- private ServerAsyncTask serverAsync;
- private HostageDBOpenHelper mDbHelper;
- private Synchronizer synchronizer;
- private void extractFromView(){
- mTxtP2PDeviceName = (TextView) findViewById(R.id.txt_p2p_device_name);
- mTxtP2PDeviceStatus = (TextView) findViewById(R.id.txt_p2p_device_status);
- mTxtP2PChangeDeviceName = (TextView) findViewById(R.id.txtP2PChangeDeviceName);
- //mTxtP2PHeader = (TextView) findViewById(R.id.txtP2PHeader);
- //mTxtP2PSubHeader = (TextView) findViewById(R.id.txtP2PSubheader);
- //mTxtP2PHelpBack = (TextView) findViewById(R.id.txtP2PHelpBack);
- //mViewAnimator = (ViewAnimator) findViewById(R.id.viewAnimator);
- mDevicesContainer = (RelativeLayout) findViewById(R.id.devicesContainer);
- //mWelcomeContainer = (RelativeLayout) findViewById(R.id.welcomeContainer);
- mTxtP2PSearchProgress = (TextView) findViewById(R.id.txtP2PSearchProgress);
- mLstP2PDevices = (ListView) findViewById(R.id.lstP2PDevices);
- //mBtnP2PSearch = (Button) findViewById(R.id.btnP2PSearch);
- mTxtP2PNotAvailable = (TextView) findViewById(R.id.txtP2PNotAvailable);
- }
- public void discoverPeers(){
- mManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {
- @Override
- public void onSuccess() {
- mViewAnimator.showNext();
- mTxtP2PSearchProgress.setVisibility(View.VISIBLE);
- setWifiDirectAvailable();
- }
- @Override
- public void onFailure(int reason) {
- if(reason == WifiP2pManager.P2P_UNSUPPORTED) {
- setWifiDirectNotAvailable();
- }
- }
- });
- }
- public void setWifiDirectNotAvailable(){
- //mBtnP2PSearch.setVisibility(View.GONE);
- mTxtP2PNotAvailable.setVisibility(View.VISIBLE);
- peers.clear();
- ((WiFiPeerListAdapter) mLstP2PDevices.getAdapter()).notifyDataSetChanged();
- mDevice = null;
- }
- public void setWifiDirectAvailable(){
- //mBtnP2PSearch.setVisibility(View.VISIBLE);
- mTxtP2PNotAvailable.setVisibility(View.GONE);
- }
- public void closeConnection(){
- if(this.serverAsync != null && !this.serverAsync.isCancelled()){
- this.serverAsync.cancel(true);
- }
- if(this.clientAsync != null && !this.clientAsync.isCancelled()){
- this.clientAsync.cancel(true);
- }
- }
- public void registerListeners(){
- mTxtP2PChangeDeviceName.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Method method1 = null;
- try {
- method1 = mManager.getClass().getDeclaredMethod("setDeviceName", WifiP2pManager.Channel.class);
- method1.invoke(mManager, mChannel, "Android_fc546");
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- }
- });
- }
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mDbHelper = new HostageDBOpenHelper(getApplicationContext());
- synchronizer = new Synchronizer(mDbHelper);
- setContentView(R.layout.activity_p2_psync);
- assert getActionBar() != null;
- getActionBar().setTitle("WifiDirect Synchronization");
- this.extractFromView();
- this.registerListeners();
- this.mLstP2PDevices.setAdapter(new WiFiPeerListAdapter(this, R.layout.row_devices, peers));
- this.mLstP2PDevices.setOnItemClickListener(this);
- mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
- mChannel = mManager.initialize(this, getMainLooper(), new WifiP2pManager.ChannelListener() {
- @Override
- public void onChannelDisconnected() {
- System.out.println("---------------------> CHannel disconnect!!!");
- }
- });
- mIntentFilter = new IntentFilter();
- mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
- mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
- mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
- mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
- this.discoverPeers();
- }
- @Override
- protected void onResume() {
- super.onResume();
- mReceiver = new P2PBroadcastReceiver(mManager, mChannel, this);
- registerReceiver(mReceiver, mIntentFilter);
- }
- @Override
- protected void onPause() {
- super.onPause();
- unregisterReceiver(mReceiver);
- }
- @Override
- public void onPeersAvailable(WifiP2pDeviceList peerList){
- mTxtP2PSearchProgress.setVisibility(View.GONE);
- peers.clear();
- peers.addAll(peerList.getDeviceList());
- ((WiFiPeerListAdapter) mLstP2PDevices.getAdapter()).notifyDataSetChanged();
- if (peers.size() == 0) {
- return;
- }
- }
- private WifiP2pDevice getConnectedPeer(){
- for(WifiP2pDevice device: peers){
- if(device.status == WifiP2pDevice.CONNECTED){
- return device;
- }
- }
- return null;
- }
- private static String getDeviceStatus(int deviceStatus) {
- switch (deviceStatus) {
- case WifiP2pDevice.AVAILABLE:
- return "Available";
- case WifiP2pDevice.INVITED:
- return "Invited";
- case WifiP2pDevice.CONNECTED:
- return "Connected";
- case WifiP2pDevice.FAILED:
- return "Failed";
- case WifiP2pDevice.UNAVAILABLE:
- return "Unavailable";
- default:
- return "Unknown";
- }
- }
- public void updateThisDevice(WifiP2pDevice device) {
- this.mDevice = device;
- mTxtP2PDeviceName.setText(device.deviceName);
- mTxtP2PDeviceStatus.setText(getDeviceStatus(device.status));
- }
- @Override
- public void onChannelDisconnected() {
- closeConnection();
- }
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- final WifiP2pDevice device = (WifiP2pDevice) this.mLstP2PDevices.getAdapter().getItem(position);
- WifiP2pConfig config = new WifiP2pConfig();
- config.deviceAddress = device.deviceAddress;
- mManager.connect(mChannel, config, new WifiP2pManager.ActionListener() {
- @Override
- public void onSuccess() {
- mOtherDevice = device;
- }
- @Override
- public void onFailure(int reason) {
- //mOtherDevice = null;
- Toast.makeText(P2PSyncActivity.this, "Could not connect to device. Retry.", Toast.LENGTH_LONG).show();
- }
- });
- }
- @Override
- public void onConnectionInfoAvailable(WifiP2pInfo info) {
- mInfo = info;
- //if(mOtherDevice == null) return;
- if(info.groupFormed && info.isGroupOwner){
- Log.i("server", "I am the group owner!");
- WifiP2pDevice connectedPeer = getConnectedPeer();
- if(connectedPeer != null && mInfo != null){
- Log.i("peers", mInfo.groupFormed + " - " + mInfo.isGroupOwner);
- Log.i("server", "Starting async server!");
- serverAsync = new ServerAsyncTask(this, OWNER_SERVER_PORT, synchronizer);
- serverAsync.execute();
- }
- //new ClientAsyncTask(this, mOtherDevice.deviceAddress, CLIENT_SERVER_PORT).execute();
- } else if(info.groupFormed){
- //new ServerAsyncTask(this, CLIENT_SERVER_PORT).execute();
- Log.i("client", "Starting async client!");
- clientAsync = new ClientAsyncTask(this, mInfo.groupOwnerAddress.getHostAddress(), OWNER_SERVER_PORT, synchronizer);
- clientAsync.execute();
- }
- }
- public void sendDatabase(boolean isOwner){
- }
- @Override
- public void onGroupInfoAvailable(WifiP2pGroup group) {
- }
- /**
- * Array adapter for ListFragment that maintains WifiP2pDevice list.
- */
- private class WiFiPeerListAdapter extends ArrayAdapter<WifiP2pDevice> {
- private List<WifiP2pDevice> items;
- /**
- * @param context
- * @param textViewResourceId
- * @param objects
- */
- public WiFiPeerListAdapter(Context context, int textViewResourceId,
- List<WifiP2pDevice> objects) {
- super(context, textViewResourceId, objects);
- items = objects;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- View v = convertView;
- if (v == null) {
- LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- v = vi.inflate(R.layout.row_devices, null);
- }
- WifiP2pDevice device = items.get(position);
- if (device != null) {
- TextView top = (TextView) v.findViewById(R.id.device_name);
- TextView bottom = (TextView) v.findViewById(R.id.device_details);
- if (top != null) {
- top.setText(device.deviceName);
- }
- if (bottom != null) {
- bottom.setText(getDeviceStatus(device.status));
- }
- }
- return v;
- }
- }
- public static class ServerAsyncTask extends AsyncTask<String, Integer, Integer> {
- private Activity context;
- private int port;
- private final ProgressDialog progressDialog;
- private final Synchronizer synchronizer;
- /**
- * @param context
- */
- public ServerAsyncTask(Activity context, int port, Synchronizer synchronizer) {
- this.context = context;
- this.port = port;
- this.progressDialog = new ProgressDialog(context);
- this.synchronizer = synchronizer;
- }
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- this.progressDialog.setMessage("Synchronizing data with other device...");
- this.progressDialog.setIndeterminate(false);
- this.progressDialog.setMax(100);
- this.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
- this.progressDialog.setCancelable(true);
- this.progressDialog.show();
- }
- @Override
- protected Integer doInBackground(String... params) {
- try {
- ServerSocket serverSocket = new ServerSocket(this.port);
- Log.i("server", "Waiting for clients!");
- Socket client = serverSocket.accept();
- Log.i("server", "Client connected!");
- publishProgress(1);
- ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
- ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
- // -- client speaks first, receive syncinfo
- SyncInfo otherSyncInfo = null;
- try {
- otherSyncInfo = (SyncInfo) ois.readObject();
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- publishProgress(2);
- // --- 1. write first message - syncinfo
- Log.i("server", "writing to client");
- SyncInfo thisSyncInfo = new SyncInfo();
- thisSyncInfo.deviceMap.put("dev1", 12L);
- thisSyncInfo.deviceMap.put("dev2", 13L);
- oos.writeObject(thisSyncInfo);
- oos.flush();
- oos.reset();
- publishProgress(3);
- // --- 2. read sync data
- SyncData syncData = null;
- try {
- syncData = (SyncData) ois.readObject();
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- publishProgress(4);
- // --- 3. send sync data
- SyncData mySyncData = new SyncData();
- //mySyncData.records.add(new Record());
- oos.writeObject(mySyncData);
- oos.flush();
- oos.reset();
- publishProgress(5);
- // --- 4. We are done!
- ois.close();
- oos.close();
- //copyFile(inputstream, new FileOutputStream(f));
- serverSocket.close();
- return 0;
- } catch (IOException e) {
- return -1;
- }
- }
- @Override
- protected void onProgressUpdate(Integer... progress) {
- this.progressDialog.setProgress(progress[0] * (100 / 5));
- }
- @Override
- protected void onPostExecute(Integer unused) {
- this.progressDialog.dismiss();
- }
- }
- public static class ClientAsyncTask extends AsyncTask<String, Integer, Integer> {
- private Context context;
- private int port;
- private String host;
- private static final int SOCKET_TIMEOUT = 10000;
- private int tryNum = 0;
- private final ProgressDialog progressDialog;
- private final Synchronizer synchronizer;
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- this.progressDialog.setMessage("Synchronizing data with other device...");
- this.progressDialog.setIndeterminate(false);
- this.progressDialog.setMax(100);
- this.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
- this.progressDialog.setCancelable(true);
- this.progressDialog.show();
- }
- /**
- * @param context
- */
- public ClientAsyncTask(Context context, String host, int port, Synchronizer synchronizer) {
- this.context = context;
- this.host = host;
- this.port = port;
- this.progressDialog = new ProgressDialog(context);
- this.synchronizer = synchronizer;
- }
- @Override
- protected Integer doInBackground(String... params) {
- Socket socket = new Socket();
- tryNum++;
- try {
- Log.i("client", "trying to connect to " + host + ":" + port);
- socket.bind(null);
- socket.connect(new InetSocketAddress(host, port), SOCKET_TIMEOUT);
- Log.i("client", "connected to server");
- publishProgress(1);
- ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
- ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
- // Client sends first!
- SyncInfo thisSyncInfo = new SyncInfo();
- thisSyncInfo.deviceMap.put("dev4", 12L);
- thisSyncInfo.deviceMap.put("dev5", 13L);
- oos.writeObject(thisSyncInfo);
- oos.flush();
- oos.reset();
- publishProgress(2);
- // --- 1. Receive sync info
- SyncInfo otherSyncInfo = null;
- try {
- otherSyncInfo = (SyncInfo) ois.readObject();
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- publishProgress(3);
- // --- 2. Send sync data
- SyncData thisSyncData = new SyncData();
- //thisSyncData.records.add(new Record());
- oos.writeObject(thisSyncData);
- oos.flush();
- oos.reset();
- publishProgress(4);
- // --- 3. Receive sync data
- SyncData otherSyncData = null;
- try {
- otherSyncData = (SyncData) ois.readObject();
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- publishProgress(5);
- // --
- ois.close();
- oos.close();
- socket.close();
- } catch (IOException e) {
- if(tryNum >= 5) {
- return -1;
- }
- long seconds_to_wait = (long) Math.min(60, Math.pow(2, tryNum));
- Log.i("client", "could not connect to server. Will try again in " + seconds_to_wait + "s");
- try {
- Thread.sleep(seconds_to_wait * 1000);
- doInBackground(params);
- } catch (InterruptedException e1) {
- e1.printStackTrace();
- }
- }
- return 0;
- }
- @Override
- protected void onProgressUpdate(Integer... progress) {
- this.progressDialog.setProgress(progress[0] * (100 / 5));
- }
- @Override
- protected void onPostExecute(Integer unused) {
- this.progressDialog.dismiss();
- }
- }
- public static boolean copyFile(InputStream inputStream, OutputStream out) {
- byte buf[] = new byte[1024];
- int len;
- try {
- while ((len = inputStream.read(buf)) != -1) {
- out.write(buf, 0, len);
- }
- out.close();
- inputStream.close();
- } catch (IOException e) {
- return false;
- }
- return true;
- }
- }
|