Home | History | Annotate | Download | only in wifidirect
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.wifidirect;
     18 
     19 import android.app.Fragment;
     20 import android.app.ProgressDialog;
     21 import android.content.Context;
     22 import android.content.DialogInterface;
     23 import android.content.Intent;
     24 import android.net.Uri;
     25 import android.net.wifi.WpsInfo;
     26 import android.net.wifi.p2p.WifiP2pConfig;
     27 import android.net.wifi.p2p.WifiP2pDevice;
     28 import android.net.wifi.p2p.WifiP2pInfo;
     29 import android.net.wifi.p2p.WifiP2pManager.ConnectionInfoListener;
     30 import android.os.AsyncTask;
     31 import android.os.Bundle;
     32 import android.os.Environment;
     33 import android.util.Log;
     34 import android.view.LayoutInflater;
     35 import android.view.View;
     36 import android.view.ViewGroup;
     37 import android.widget.TextView;
     38 
     39 import com.example.android.wifidirect.DeviceListFragment.DeviceActionListener;
     40 
     41 import java.io.File;
     42 import java.io.FileOutputStream;
     43 import java.io.IOException;
     44 import java.io.InputStream;
     45 import java.io.OutputStream;
     46 import java.net.ServerSocket;
     47 import java.net.Socket;
     48 
     49 /**
     50  * A fragment that manages a particular peer and allows interaction with device
     51  * i.e. setting up network connection and transferring data.
     52  */
     53 public class DeviceDetailFragment extends Fragment implements ConnectionInfoListener {
     54 
     55     protected static final int CHOOSE_FILE_RESULT_CODE = 20;
     56     private View mContentView = null;
     57     private WifiP2pDevice device;
     58     private WifiP2pInfo info;
     59     ProgressDialog progressDialog = null;
     60 
     61     @Override
     62     public void onActivityCreated(Bundle savedInstanceState) {
     63         super.onActivityCreated(savedInstanceState);
     64     }
     65 
     66     @Override
     67     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
     68 
     69         mContentView = inflater.inflate(R.layout.device_detail, null);
     70         mContentView.findViewById(R.id.btn_connect).setOnClickListener(new View.OnClickListener() {
     71 
     72             @Override
     73             public void onClick(View v) {
     74                 WifiP2pConfig config = new WifiP2pConfig();
     75                 config.deviceAddress = device.deviceAddress;
     76                 config.wps.setup = WpsInfo.PBC;
     77                 if (progressDialog != null && progressDialog.isShowing()) {
     78                     progressDialog.dismiss();
     79                 }
     80                 progressDialog = ProgressDialog.show(getActivity(), "Press back to cancel",
     81                         "Connecting to :" + device.deviceAddress, true, true
     82 //                        new DialogInterface.OnCancelListener() {
     83 //
     84 //                            @Override
     85 //                            public void onCancel(DialogInterface dialog) {
     86 //                                ((DeviceActionListener) getActivity()).cancelDisconnect();
     87 //                            }
     88 //                        }
     89                         );
     90                 ((DeviceActionListener) getActivity()).connect(config);
     91 
     92             }
     93         });
     94 
     95         mContentView.findViewById(R.id.btn_disconnect).setOnClickListener(
     96                 new View.OnClickListener() {
     97 
     98                     @Override
     99                     public void onClick(View v) {
    100                         ((DeviceActionListener) getActivity()).disconnect();
    101                     }
    102                 });
    103 
    104         mContentView.findViewById(R.id.btn_start_client).setOnClickListener(
    105                 new View.OnClickListener() {
    106 
    107                     @Override
    108                     public void onClick(View v) {
    109                         // Allow user to pick an image from Gallery or other
    110                         // registered apps
    111                         Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    112                         intent.setType("image/*");
    113                         startActivityForResult(intent, CHOOSE_FILE_RESULT_CODE);
    114                     }
    115                 });
    116 
    117         return mContentView;
    118     }
    119 
    120     @Override
    121     public void onActivityResult(int requestCode, int resultCode, Intent data) {
    122 
    123         // User has picked an image. Transfer it to group owner i.e peer using
    124         // FileTransferService.
    125         Uri uri = data.getData();
    126         TextView statusText = (TextView) mContentView.findViewById(R.id.status_text);
    127         statusText.setText("Sending: " + uri);
    128         Log.d(WiFiDirectActivity.TAG, "Intent----------- " + uri);
    129         Intent serviceIntent = new Intent(getActivity(), FileTransferService.class);
    130         serviceIntent.setAction(FileTransferService.ACTION_SEND_FILE);
    131         serviceIntent.putExtra(FileTransferService.EXTRAS_FILE_PATH, uri.toString());
    132         serviceIntent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_ADDRESS,
    133                 info.groupOwnerAddress.getHostAddress());
    134         serviceIntent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_PORT, 8988);
    135         getActivity().startService(serviceIntent);
    136     }
    137 
    138     @Override
    139     public void onConnectionInfoAvailable(final WifiP2pInfo info) {
    140         if (progressDialog != null && progressDialog.isShowing()) {
    141             progressDialog.dismiss();
    142         }
    143         this.info = info;
    144         this.getView().setVisibility(View.VISIBLE);
    145 
    146         // The owner IP is now known.
    147         TextView view = (TextView) mContentView.findViewById(R.id.group_owner);
    148         view.setText(getResources().getString(R.string.group_owner_text)
    149                 + ((info.isGroupOwner == true) ? getResources().getString(R.string.yes)
    150                         : getResources().getString(R.string.no)));
    151 
    152         // InetAddress from WifiP2pInfo struct.
    153         view = (TextView) mContentView.findViewById(R.id.device_info);
    154         view.setText("Group Owner IP - " + info.groupOwnerAddress.getHostAddress());
    155 
    156         // After the group negotiation, we assign the group owner as the file
    157         // server. The file server is single threaded, single connection server
    158         // socket.
    159         if (info.groupFormed && info.isGroupOwner) {
    160             new FileServerAsyncTask(getActivity(), mContentView.findViewById(R.id.status_text))
    161                     .execute();
    162         } else if (info.groupFormed) {
    163             // The other device acts as the client. In this case, we enable the
    164             // get file button.
    165             mContentView.findViewById(R.id.btn_start_client).setVisibility(View.VISIBLE);
    166             ((TextView) mContentView.findViewById(R.id.status_text)).setText(getResources()
    167                     .getString(R.string.client_text));
    168         }
    169 
    170         // hide the connect button
    171         mContentView.findViewById(R.id.btn_connect).setVisibility(View.GONE);
    172     }
    173 
    174     /**
    175      * Updates the UI with device data
    176      *
    177      * @param device the device to be displayed
    178      */
    179     public void showDetails(WifiP2pDevice device) {
    180         this.device = device;
    181         this.getView().setVisibility(View.VISIBLE);
    182         TextView view = (TextView) mContentView.findViewById(R.id.device_address);
    183         view.setText(device.deviceAddress);
    184         view = (TextView) mContentView.findViewById(R.id.device_info);
    185         view.setText(device.toString());
    186 
    187     }
    188 
    189     /**
    190      * Clears the UI fields after a disconnect or direct mode disable operation.
    191      */
    192     public void resetViews() {
    193         mContentView.findViewById(R.id.btn_connect).setVisibility(View.VISIBLE);
    194         TextView view = (TextView) mContentView.findViewById(R.id.device_address);
    195         view.setText(R.string.empty);
    196         view = (TextView) mContentView.findViewById(R.id.device_info);
    197         view.setText(R.string.empty);
    198         view = (TextView) mContentView.findViewById(R.id.group_owner);
    199         view.setText(R.string.empty);
    200         view = (TextView) mContentView.findViewById(R.id.status_text);
    201         view.setText(R.string.empty);
    202         mContentView.findViewById(R.id.btn_start_client).setVisibility(View.GONE);
    203         this.getView().setVisibility(View.GONE);
    204     }
    205 
    206     /**
    207      * A simple server socket that accepts connection and writes some data on
    208      * the stream.
    209      */
    210     public static class FileServerAsyncTask extends AsyncTask<Void, Void, String> {
    211 
    212         private Context context;
    213         private TextView statusText;
    214 
    215         /**
    216          * @param context
    217          * @param statusText
    218          */
    219         public FileServerAsyncTask(Context context, View statusText) {
    220             this.context = context;
    221             this.statusText = (TextView) statusText;
    222         }
    223 
    224         @Override
    225         protected String doInBackground(Void... params) {
    226             try {
    227                 ServerSocket serverSocket = new ServerSocket(8988);
    228                 Log.d(WiFiDirectActivity.TAG, "Server: Socket opened");
    229                 Socket client = serverSocket.accept();
    230                 Log.d(WiFiDirectActivity.TAG, "Server: connection done");
    231                 final File f = new File(Environment.getExternalStorageDirectory() + "/"
    232                         + context.getPackageName() + "/wifip2pshared-" + System.currentTimeMillis()
    233                         + ".jpg");
    234 
    235                 File dirs = new File(f.getParent());
    236                 if (!dirs.exists())
    237                     dirs.mkdirs();
    238                 f.createNewFile();
    239 
    240                 Log.d(WiFiDirectActivity.TAG, "server: copying files " + f.toString());
    241                 InputStream inputstream = client.getInputStream();
    242                 copyFile(inputstream, new FileOutputStream(f));
    243                 serverSocket.close();
    244                 return f.getAbsolutePath();
    245             } catch (IOException e) {
    246                 Log.e(WiFiDirectActivity.TAG, e.getMessage());
    247                 return null;
    248             }
    249         }
    250 
    251         /*
    252          * (non-Javadoc)
    253          * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
    254          */
    255         @Override
    256         protected void onPostExecute(String result) {
    257             if (result != null) {
    258                 statusText.setText("File copied - " + result);
    259                 Intent intent = new Intent();
    260                 intent.setAction(android.content.Intent.ACTION_VIEW);
    261                 intent.setDataAndType(Uri.parse("file://" + result), "image/*");
    262                 context.startActivity(intent);
    263             }
    264 
    265         }
    266 
    267         /*
    268          * (non-Javadoc)
    269          * @see android.os.AsyncTask#onPreExecute()
    270          */
    271         @Override
    272         protected void onPreExecute() {
    273             statusText.setText("Opening a server socket");
    274         }
    275 
    276     }
    277 
    278     public static boolean copyFile(InputStream inputStream, OutputStream out) {
    279         byte buf[] = new byte[1024];
    280         int len;
    281         try {
    282             while ((len = inputStream.read(buf)) != -1) {
    283                 out.write(buf, 0, len);
    284 
    285             }
    286             out.close();
    287             inputStream.close();
    288         } catch (IOException e) {
    289             Log.d(WiFiDirectActivity.TAG, e.toString());
    290             return false;
    291         }
    292         return true;
    293     }
    294 
    295 }
    296