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