Browse Source

Implemented WiFi P2p Activity. Implemented Sync Host and Server Task.

Julien Clauter 9 years ago
parent
commit
42f9b1c8b3

+ 24 - 2
src/de/tudarmstadt/informatik/hostage/sync/wifi_direct/BackgroundTask.java

@@ -8,6 +8,11 @@ import android.os.AsyncTask;
  */
 public class BackgroundTask extends AsyncTask<Void, Void, String> {
 
+    public interface BackgroundTaskCompletionListener {
+        public void didSucceed();
+        public void didFail();
+    }
+
     private boolean isInterrupted;
 
     public void interrupt(boolean b){
@@ -18,18 +23,35 @@ public class BackgroundTask extends AsyncTask<Void, Void, String> {
         return isInterrupted;
     }
 
+    private BackgroundTaskCompletionListener completion_listener;
+
+    public BackgroundTask(BackgroundTaskCompletionListener l){
+        super();
+        this.completion_listener = l;
+    }
+
     public void setInterrupted(boolean isInterrupted) {
         this.isInterrupted = isInterrupted;
     }
 
 
-    public void performInBackground(){
 
+    public boolean performInBackground(){
+        return true;
     }
 
     @Override
     protected String doInBackground(Void... params) {
-        this.performInBackground();
+        boolean success = this.performInBackground();
+
+        if (this.completion_listener != null) {
+            if (success){
+                this.completion_listener.didSucceed();
+            }else {
+                this.completion_listener.didFail();
+            }
+        }
+
         return null;
     }
 

+ 330 - 0
src/de/tudarmstadt/informatik/hostage/sync/wifi_direct/UI/WiFiP2pSyncActivity.java

@@ -0,0 +1,330 @@
+package de.tudarmstadt.informatik.hostage.sync.wifi_direct.ui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.net.wifi.p2p.WifiP2pDevice;
+import android.net.wifi.p2p.WifiP2pInfo;
+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.util.ArrayList;
+import java.util.List;
+
+import de.tudarmstadt.informatik.hostage.R;
+import de.tudarmstadt.informatik.hostage.sync.wifi_direct.BackgroundTask;
+import de.tudarmstadt.informatik.hostage.sync.wifi_direct.WiFiP2pEventHandler;
+import de.tudarmstadt.informatik.hostage.sync.wifi_direct.sync_tasks.SyncClientTask;
+import de.tudarmstadt.informatik.hostage.sync.wifi_direct.sync_tasks.SyncHostTask;
+
+/**
+ * Created by Julien on 14.01.2015.
+ */
+public class WiFiP2pSyncActivity extends Activity implements AdapterView.OnItemClickListener {
+
+    private SyncClientTask clientTask;
+    private SyncHostTask  hostTask;
+    private boolean isHost;
+
+    private WiFiP2pEventHandler _wifiEventHandler = null;
+
+    private WiFiP2pEventHandler.WiFiP2pEventListener _p2pEventListener = null;
+    private BackgroundTask.BackgroundTaskCompletionListener _syncCompletionListener = null;
+
+
+    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;
+
+
+    public boolean isHost() {
+        return isHost;
+    }
+
+    public void setHost(boolean isHost) {
+        this.isHost = isHost;
+    }
+
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        this.wifiEventHandler();
+
+        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, new ArrayList()));
+        this.mLstP2PDevices.setOnItemClickListener(this);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        this.wifiEventHandler().onResume();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        this.wifiEventHandler().onPause();
+    }
+
+    private WiFiP2pEventHandler.WiFiP2pEventListener eventListener(){
+        if (_p2pEventListener == null){
+            _p2pEventListener = new WiFiP2pEventHandler.WiFiP2pEventListener() {
+                WiFiP2pSyncActivity activity = null;
+                public WiFiP2pEventHandler.WiFiP2pEventListener init(WiFiP2pSyncActivity act){
+                    this.activity = act;
+                    return this;
+                }
+
+                @Override
+                public void discoveredDevices(List<WifiP2pDevice> peers) {
+                    Log.d("WiFiP2pSyncActivity", "Actualise devices" + ".");
+                    this.activity.refreshDeviceList(peers);
+                }
+
+                @Override
+                public void wifiP2pIsEnabled(boolean enabled) {
+                    String tmp = enabled? "enabled" : "disabled";
+                    Log.d("WiFiP2pSyncActivity", "Peer to peer is " + tmp + ".");
+                    if (!enabled){
+                        Toast.makeText(this.activity, "WiFi Direct P2P is disabled.", Toast.LENGTH_LONG).show();
+                    }
+                }
+
+                @Override
+                public void didConnect(boolean isHost, WifiP2pInfo connectionInfo) {
+                    Log.d("WiFiP2pSyncActivity", "Did connect" + ".");
+                    this.activity.setHost(isHost);
+                    if (isHost){
+                        Log.d("WiFiP2pSyncActivity", "Connected as HOST" + ".");
+                        this.activity.startHost();
+                    } else {
+                        Log.d("WiFiP2pSyncActivity", "Connected as Client" + ".");
+                        this.activity.startClient(connectionInfo);
+                    }
+                }
+
+                @Override
+                public void failedToConnect() {
+                    Log.d("WiFiP2pSyncActivity", "Failed to connect" + ".");
+                    Toast.makeText(this.activity, "Could not connect to device. Retry.", Toast.LENGTH_LONG).show();
+                }
+
+                @Override
+                public void didDisconnect() {
+                    Log.d("WiFiP2pSyncActivity", "Did disconnect" + ".");
+
+                }
+
+                @Override
+                public void failedToDisconnect() {
+                    Log.d("WiFiP2pSyncActivity", "Failed to disconnect" + ".");
+                    Toast.makeText(this.activity, "Could not disconnect with device. Retry.", Toast.LENGTH_LONG).show();
+                }
+
+                @Override
+                public void deviceIsUpdated(WifiP2pDevice device) {
+                    Log.d("WiFiP2pSyncActivity", "Updated device " + device.deviceName + " " + device.deviceAddress + ".");
+                    this.activity.updateDevice(device);
+                }
+            }.init(this);
+        }
+
+        return _p2pEventListener;
+    }
+
+    private WiFiP2pEventHandler wifiEventHandler(){
+        if (this._wifiEventHandler == null){
+            this._wifiEventHandler = new WiFiP2pEventHandler(this, this.eventListener());
+        }
+        return this._wifiEventHandler;
+    }
+
+
+
+    private BackgroundTask.BackgroundTaskCompletionListener syncCompletionListener(){
+        if (_syncCompletionListener == null){
+            _syncCompletionListener = new BackgroundTask.BackgroundTaskCompletionListener() {
+                WiFiP2pSyncActivity activity = null;
+                public BackgroundTask.BackgroundTaskCompletionListener init(WiFiP2pSyncActivity act){
+                    this.activity = act;
+                    return this;
+                }
+                @Override
+                public void didSucceed() {
+                    Toast.makeText(this.activity, "Synchronization complete.", Toast.LENGTH_SHORT).show();
+                }
+
+                @Override
+                public void didFail() {
+                    Toast.makeText(this.activity, "Could not synchronize with device. Retry.", Toast.LENGTH_LONG).show();
+                }
+            }.init(this);
+        }
+        return _syncCompletionListener;
+    }
+
+
+    private void refreshDeviceList(List<WifiP2pDevice> peers){
+        this.mLstP2PDevices.setAdapter(new WiFiPeerListAdapter(this, R.layout.row_devices, peers));
+    }
+
+    private void startHost(){
+        Log.d("WiFiP2pSyncActivity", "Starting HOST Task" + ".");
+        Toast.makeText(this, "Acting as Host.", Toast.LENGTH_SHORT).show();
+        this.hostTask = new SyncHostTask(this.syncCompletionListener(), getApplicationContext());
+    }
+
+    private void startClient(WifiP2pInfo info){
+        Log.d("WiFiP2pSyncActivity", "Starting CLIENT Task" + ".");
+        Toast.makeText(this, "Acting as Client.", Toast.LENGTH_SHORT).show();
+        this.clientTask = new SyncClientTask("" + info.groupOwnerAddress, this.syncCompletionListener(), getApplicationContext() );
+    }
+
+
+    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";
+        }
+    }
+
+
+    private void updateDevice(WifiP2pDevice device){
+        mTxtP2PDeviceName.setText(device.deviceName);
+        mTxtP2PDeviceStatus.setText(getDeviceStatus(device.status));
+        mDevice = device;
+    }
+
+    /********************** UI ************************/
+
+
+    public void setWifiDirectAvailable(boolean enabled){
+        if (enabled){
+            mTxtP2PNotAvailable.setVisibility(View.GONE);
+        } else {
+            mTxtP2PNotAvailable.setVisibility(View.VISIBLE);
+            ((WiFiPeerListAdapter) mLstP2PDevices.getAdapter()).notifyDataSetChanged();
+            mDevice = null;
+            this.refreshDeviceList(new ArrayList<WifiP2pDevice>());
+        }
+    }
+
+
+
+    private void extractFromView(){
+        this.mTxtP2PDeviceName = (TextView) findViewById(R.id.txt_p2p_device_name);
+        this.mTxtP2PDeviceStatus = (TextView) findViewById(R.id.txt_p2p_device_status);
+        this.mTxtP2PChangeDeviceName = (TextView) findViewById(R.id.txtP2PChangeDeviceName);
+
+        this.mViewAnimator = (ViewAnimator) findViewById(R.id.viewAnimator);
+        this.mDevicesContainer = (RelativeLayout) findViewById(R.id.devicesContainer);
+        this.mWelcomeContainer = (RelativeLayout) findViewById(R.id.welcomeContainer);
+        this.mTxtP2PSearchProgress = (TextView) findViewById(R.id.txtP2PSearchProgress);
+        this.mLstP2PDevices = (ListView) findViewById(R.id.lstP2PDevices);
+        this.mTxtP2PNotAvailable = (TextView) findViewById(R.id.txtP2PNotAvailable);
+    }
+
+    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
+    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+        final WifiP2pDevice device = (WifiP2pDevice) this.mLstP2PDevices.getAdapter().getItem(position);
+        this.wifiEventHandler().connect(device);
+        mOtherDevice = device;
+    }
+
+
+    /**
+     * 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;
+        }
+    }
+}

+ 7 - 14
src/de/tudarmstadt/informatik/hostage/sync/wifi_direct/WiFiP2pClientTask.java

@@ -15,14 +15,10 @@ import java.net.Socket;
  */
 public class WiFiP2pClientTask extends BackgroundTask {
 
-    public interface WiFiP2pCompletionListener {
-        public void didSucceed();
-        public void didFail();
-    }
+
 
     private String hostIP;
     private Socket socket;
-    private WiFiP2pCompletionListener completionListener;
 
     public String getHostIP() {
         return hostIP;
@@ -41,10 +37,9 @@ public class WiFiP2pClientTask extends BackgroundTask {
     }
 
 
-    public WiFiP2pClientTask(String hostIP, WiFiP2pCompletionListener l){
-        super();
+    public WiFiP2pClientTask(String hostIP, BackgroundTaskCompletionListener l){
+        super(l);
         this.hostIP = hostIP;
-        this.completionListener = l;
     }
 
 
@@ -61,7 +56,7 @@ public class WiFiP2pClientTask extends BackgroundTask {
     }
 
     @Override
-    public void performInBackground(){
+    public boolean performInBackground(){
         int tryNum = 0;
         while (!this.isInterrupted()){
             this.socket = new Socket();
@@ -77,8 +72,7 @@ public class WiFiP2pClientTask extends BackgroundTask {
                 Log.d("WiFiP2pClientTask", "Client: Data written");
             } catch (ClassNotFoundException e){
                 Log.e("WiFiP2pClientTask", e.getMessage());
-                this.completionListener.didFail();
-                return;
+                return false;
             } catch (IOException e) {
                 Log.e("WiFiP2pClientTask", e.getMessage());
 
@@ -102,14 +96,13 @@ public class WiFiP2pClientTask extends BackgroundTask {
                         } catch (IOException e) {
                             // Give up
                             e.printStackTrace();
-                            this.completionListener.didFail();
-                            return;
+                            return false;
                         }
                     }
                 }
             }
         }
-        this.completionListener.didSucceed();
+        return true;
     }
 
 

+ 8 - 4
src/de/tudarmstadt/informatik/hostage/sync/wifi_direct/WiFiP2pServerTask.java

@@ -1,10 +1,7 @@
 package de.tudarmstadt.informatik.hostage.sync.wifi_direct;
 
-import android.os.Environment;
 import android.util.Log;
 
-import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.ObjectInputStream;
@@ -32,8 +29,12 @@ public class WiFiP2pServerTask extends BackgroundTask {
         }
     }
 
+    public WiFiP2pServerTask(BackgroundTaskCompletionListener l){
+        super(l);
+    }
+
     @Override
-    public void performInBackground(){
+    public boolean performInBackground(){
         while (!this.isInterrupted()){
             try {
                 this.serverSocket = new ServerSocket(8988);
@@ -47,10 +48,13 @@ public class WiFiP2pServerTask extends BackgroundTask {
                 serverSocket.close();
             } catch (ClassNotFoundException e){
                 Log.e("WiFiP2pServerTask", e.getMessage());
+                return false;
             } catch (IOException  e) {
                 Log.e("WiFiP2pServerTask", e.getMessage());
+                return false;
             }
         }
+        return true;
     }
 
 

+ 71 - 0
src/de/tudarmstadt/informatik/hostage/sync/wifi_direct/sync_tasks/SyncClientTask.java

@@ -0,0 +1,71 @@
+package de.tudarmstadt.informatik.hostage.sync.wifi_direct.sync_tasks;
+
+import android.content.Context;
+import android.util.Log;
+
+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.sync.wifi_direct.WiFiP2pClientTask;
+import de.tudarmstadt.informatik.hostage.sync.wifi_direct.WiFiP2pSerializableObject;
+
+
+
+/**
+ * Created by Julien on 14.01.2015.
+ */
+public class SyncClientTask extends WiFiP2pClientTask {
+
+    private HostageDBOpenHelper mdbh;
+    private Synchronizer synchronizer;
+
+    public SyncClientTask(String hostIP, BackgroundTaskCompletionListener l, Context context) {
+        super(hostIP, l);
+
+        mdbh = new HostageDBOpenHelper(context);
+        synchronizer = new Synchronizer(mdbh);
+    }
+
+    @Override
+    public WiFiP2pSerializableObject handleReceivedObject(WiFiP2pSerializableObject receivedObj) {
+
+        if (receivedObj == null) {
+            SyncInfo thisSyncInfo = synchronizer.getSyncInfo();
+            WiFiP2pSerializableObject syncObj = new WiFiP2pSerializableObject();
+
+            syncObj.setObjectToSend(thisSyncInfo);
+            syncObj.setMethodName(SyncHostTask.SYNC_INFO_REQUEST);
+
+            return syncObj;
+
+        } else {
+            Log.i("WiFi Direct Client", "Received: " + receivedObj.getMethodName());
+            if (receivedObj.getMethodName().equals(SyncHostTask.SYNC_INFO_RESPONSE)) {
+                SyncInfo sinfo = (SyncInfo) receivedObj.getObjectToSend();
+
+                if (sinfo != null && sinfo.getClass().isInstance(SyncInfo.class)) {
+                    SyncData syncData = synchronizer.getSyncData(sinfo);
+                    WiFiP2pSerializableObject syncObj = new WiFiP2pSerializableObject();
+
+                    syncObj.setObjectToSend(syncData);
+                    syncObj.setMethodName(SyncHostTask.SYNC_DATA_REQUEST);
+
+                    return syncObj;
+                }
+
+            } else if (receivedObj.getMethodName().equals(SyncHostTask.SYNC_DATA_RESPONSE)) {
+                SyncData sdata = (SyncData) receivedObj.getObjectToSend();
+
+                if (sdata != null && sdata.getClass().isInstance(SyncData.class)) {
+                    synchronizer.updateFromSyncData(sdata);
+                }
+            }
+        }
+
+        // DISCONNECT
+        this.interrupt(true);
+
+        return null;
+    }
+}

+ 76 - 0
src/de/tudarmstadt/informatik/hostage/sync/wifi_direct/sync_tasks/SyncHostTask.java

@@ -0,0 +1,76 @@
+package de.tudarmstadt.informatik.hostage.sync.wifi_direct.sync_tasks;
+
+import android.content.Context;
+import android.util.Log;
+
+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.sync.wifi_direct.WiFiP2pSerializableObject;
+import de.tudarmstadt.informatik.hostage.sync.wifi_direct.WiFiP2pServerTask;
+
+/**
+ * Created by Julien on 14.01.2015.
+ */
+public class SyncHostTask extends WiFiP2pServerTask {
+
+
+    public static final String SYNC_INFO_REQUEST = "sync_info_request";
+    public static final String SYNC_INFO_RESPONSE = "sync_info_response";
+
+    public static final String SYNC_DATA_REQUEST = "sync_data_request";
+    public static final String SYNC_DATA_RESPONSE = "sync_data_response";
+
+    private HostageDBOpenHelper mdbh;
+    private Synchronizer synchronizer;
+
+    private SyncInfo receivedInfo;
+
+    public SyncHostTask(BackgroundTaskCompletionListener l , Context context) {
+        super(l);
+        mdbh = new HostageDBOpenHelper(context);
+        synchronizer = new Synchronizer(mdbh);
+    }
+
+    @Override
+    public WiFiP2pSerializableObject handleReceivedObject(WiFiP2pSerializableObject receivedObj){
+        if (receivedObj != null) {
+            Log.i("WiFi Direct Host", "Received: " + receivedObj.getMethodName());
+
+            if (receivedObj.getMethodName().equals(SYNC_INFO_REQUEST)){
+                this.receivedInfo = (SyncInfo) receivedObj.getObjectToSend();
+
+                SyncInfo response = synchronizer.getSyncInfo();
+                WiFiP2pSerializableObject syncObj = new WiFiP2pSerializableObject();
+
+                syncObj.setObjectToSend(response);
+                syncObj.setMethodName(SYNC_INFO_RESPONSE);
+
+                return syncObj;
+            }
+
+            if (receivedObj.getMethodName().equals(SYNC_DATA_REQUEST)){
+                SyncData sdata = (SyncData) receivedObj.getObjectToSend();
+
+                if (sdata != null && sdata.getClass().isInstance(SyncData.class)){
+                    synchronizer.updateFromSyncData(sdata);
+                }
+
+                if (this.receivedInfo != null){
+                    SyncData response = synchronizer.getSyncData(this.receivedInfo);
+
+                    WiFiP2pSerializableObject syncObj = new WiFiP2pSerializableObject();
+                    syncObj.setObjectToSend(response);
+                    syncObj.setMethodName(SYNC_DATA_RESPONSE);
+
+                    return syncObj;
+                }
+            }
+        }
+
+        // DISCONNECT
+        this.interrupt(true);
+        return null;
+    }
+}