upload android base code part7
18
android/development/samples/WiFiDirectDemo/Android.mk
Normal file
|
@ -0,0 +1,18 @@
|
|||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE_TAGS := samples
|
||||
|
||||
# Only compile source java files in this apk.
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
|
||||
LOCAL_PACKAGE_NAME := WiFiDirectDemo
|
||||
|
||||
LOCAL_SDK_VERSION := current
|
||||
|
||||
LOCAL_DEX_PREOPT := false
|
||||
|
||||
include $(BUILD_PACKAGE)
|
||||
|
||||
# Use the following include to make our test apk.
|
||||
include $(call all-makefiles-under,$(LOCAL_PATH))
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.wifidirect"
|
||||
android:versionCode="1" android:versionName="1.0">
|
||||
|
||||
<uses-sdk android:minSdkVersion="14" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<!-- Google Play filtering -->
|
||||
<uses-feature android:name="android.hardware.wifi.direct" android:required="true"/>
|
||||
|
||||
<application
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@android:style/Theme.Holo">
|
||||
<activity
|
||||
android:name=".WiFiDirectActivity"
|
||||
android:label="@string/app_name" android:launchMode="singleTask">
|
||||
<intent-filter>
|
||||
<action
|
||||
android:name="android.intent.action.MAIN" />
|
||||
<category
|
||||
android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!-- Used for transferring files after a successful connection -->
|
||||
<service android:enabled="true" android:name=".FileTransferService" />
|
||||
|
||||
</application>
|
||||
</manifest>
|
49
android/development/samples/WiFiDirectDemo/_index.html
Normal file
|
@ -0,0 +1,49 @@
|
|||
<p>This is a demo application highlighting how to make peer to peer network connections with
|
||||
the Wi-Fi Direct APIs. The application allows you to transfer jpeg images from the gallery after a succesful connection.</p>
|
||||
|
||||
<p>The source code for this demo app shows how to accomplish three key things
|
||||
with Wi-Fi Direct APIs: Discovering peers, connecting using Wi-Fi Direct APIs, and finding group details post connection, so that a
|
||||
TCP socket can be opened to transfer files.</p>
|
||||
|
||||
<p>The application includes:<p>
|
||||
<ul> <li><a
|
||||
href="src/com/example/android/wifidirect/WiFiDirectActivity.html"><code>WiFiDirectActivity</code></a>
|
||||
— the main <code>Activity</code> that contains two fragments to handle app's UI and peer lifecycle. It also registers a broadcast receiver for Wi-Fi Direct related events.</li> <li><a
|
||||
href="src/com/example/android/wifidirect/WiFiDirectBroadcastReceiver.html"><code>
|
||||
WiFiDirectBroadcastReceiver</code></a> — a <code>BroadcastReceiver</code>
|
||||
that listens for Wi-Fi Direct related events and passes them to
|
||||
<code>WiFiDirectActivity</code> and it's fragments for neccesary action.</li> <li><a
|
||||
href="src/com/example/android/wifidirect/DeviceListFragment.html"><code>DeviceListFragment</code></a>
|
||||
— a <code>ListFragment</code> that displays available peers and their status. </li>
|
||||
<li><a href="src/com/example/android/wifidirect/DeviceDetailFragment.html"><code>DeviceDetailFragment</code></a>
|
||||
— a <code>Fragment</code> that displays the details of the selected device and also drives the connection, disonnection and data transfer functionality of the demo. </li>
|
||||
<li><a href="src/com/example/android/wifidirect/FileTransferService.html"><code>FileTransferService</code></a>
|
||||
— an <code>IntentService</code> that services file transfer requests from the application by using TCP sockets. </li> </ul>
|
||||
<p>If you are developing an application that uses the Wi-Fi Direct APIs, remember that the
|
||||
feature is supported only on Android 4.0 (API level 14) and higher versions of
|
||||
the platform. To ensure that your application can only
|
||||
be installed on devices that are capable of supporting Wi-Fi Direct mode, remember to add the
|
||||
following to the application's manifest before publishing to Google Play:</p>
|
||||
<ul> <li><code><uses-sdk android:minSdkVersion="14" /></code>, which
|
||||
indicates to Google Play and the platform that your application requires
|
||||
Android 4.0 or higher. For more information, see <a
|
||||
href="../../../guide/appendix/api-levels.html">API Levels</a> and the
|
||||
documentation for the <a
|
||||
href="../../../guide/topics/manifest/uses-sdk-element.html"><code><uses-sdk></code></a>
|
||||
element.</li> </ul> <p>To control how Google Play filters your application
|
||||
from devices that do not support Wi-Fi Direct mode, remember to add the following to the
|
||||
application's manifest <ul> <li><code><uses-feature
|
||||
android:name="android.hardware.wifi.direct" /></code>, which tells Google
|
||||
Play that your application uses the Wi-Fi Direct API. The declaration should include
|
||||
an <code>android:required</code> attribute that indicates whether you want
|
||||
Google Play to filter the application from devices that do not offer Wi-Fi Direct support. Other <code><uses-feature></code> declarations may also be
|
||||
needed, depending on your implementation. For more information, see the
|
||||
documentation for the <a
|
||||
href="../../../guide/topics/manifest/uses-feature-element.html"><code><uses-feature></code></a>
|
||||
element.</li> </ul>
|
||||
<p>For more information about using the Wi-Fi Direct API, see the <a
|
||||
href="../../../reference/android/net/wifi/p2p/package-summary.html"><code>android.net.wifi.p2p </a></code>
|
||||
documentation. </p>
|
||||
|
||||
<img alt="" src="../images/WifiDirect.png" />
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
This is a sample text file for wifi_direct demo.
|
||||
|
||||
Once the devices are connected, the server i.e. groupOwner will listen for incoming connections and write this file.
|
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 4 KiB |
After Width: | Height: | Size: 484 B |
After Width: | Height: | Size: 486 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 583 B |
After Width: | Height: | Size: 646 B |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 2 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 8.8 KiB |
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<solid android:color="@color/layout_border_color"/>
|
||||
<stroke
|
||||
android:width="4dp"
|
||||
android:color="@android:color/background_dark" />
|
||||
<padding
|
||||
android:left="10dp"
|
||||
android:top="2dp"
|
||||
android:right="10dp"
|
||||
android:bottom="2dp" />
|
||||
</shape>
|
After Width: | Height: | Size: 3.8 KiB |
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="@color/layout_border_color" />
|
||||
|
||||
<padding
|
||||
android:left="10dp"
|
||||
android:top="5dp"
|
||||
android:right="10dp"
|
||||
android:bottom="2dp" />
|
||||
<corners
|
||||
android:radius="2dp" />
|
||||
</shape>
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/linearLayout1"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
<fragment
|
||||
class="com.example.android.wifidirect.DeviceListFragment"
|
||||
android:id="@+id/frag_list"
|
||||
android:layout_width="@dimen/phone_list_height"
|
||||
android:layout_height="match_parent">
|
||||
<!-- Preview: layout=@layout/row_devices -->
|
||||
</fragment>
|
||||
<fragment
|
||||
class="com.example.android.wifidirect.DeviceDetailFragment"
|
||||
android:id="@+id/frag_detail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<!-- Preview: layout=@layout/device_detail -->
|
||||
</fragment>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical" android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<LinearLayout android:layout_width="match_parent" android:id="@+id/linearLayout1"
|
||||
android:layout_height="fill_parent" android:orientation="horizontal">
|
||||
<fragment class="com.example.android.wifidirect.DeviceListFragment"
|
||||
android:id="@+id/frag_list" android:layout_width="@dimen/tablet_list_width"
|
||||
android:layout_height="match_parent">
|
||||
<!-- Preview: layout=@layout/row_devices -->
|
||||
</fragment>
|
||||
<fragment class="com.example.android.wifidirect.DeviceDetailFragment"
|
||||
android:id="@+id/frag_detail" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<!-- Preview: layout=@layout/device_detail -->
|
||||
</fragment>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,70 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:background="@drawable/details_view"
|
||||
android:visibility="gone">
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<Button
|
||||
android:id="@+id/btn_connect"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/connect_peer_button" />
|
||||
<Button
|
||||
android:id="@+id/btn_disconnect"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/disconnect_peer_button" />
|
||||
<Button
|
||||
android:id="@+id/btn_start_client"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/get_file_button"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@+id/device_address"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
<TextView
|
||||
android:id="@+id/device_info"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
<TextView
|
||||
android:id="@+id/group_owner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
<TextView
|
||||
android:id="@+id/group_ip"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/status_bar"
|
||||
android:orientation="vertical"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_height="37dp"
|
||||
android:layout_marginBottom="3dp"
|
||||
android:background="@android:color/background_dark">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="5dp"
|
||||
android:textColor="@android:color/white"
|
||||
android:id="@+id/status_text">
|
||||
</TextView>
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
|
@ -0,0 +1,80 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingTop="3dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/label_me" />
|
||||
<View
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="1dp"
|
||||
android:gravity="center_vertical"
|
||||
android:background="@android:color/holo_blue_light" />
|
||||
|
||||
<!-- Self information -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="?android:attr/listPreferredItemHeight"
|
||||
android:background="?android:attr/activatedBackgroundIndicator"
|
||||
android:padding="3dip">
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_marginRight="2dp"
|
||||
android:src="@drawable/machine" />
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="fill_parent">
|
||||
<TextView
|
||||
android:id="@+id/my_name"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical" />
|
||||
<TextView
|
||||
android:id="@+id/my_status"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/label_peers" />
|
||||
|
||||
<View
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="1dp"
|
||||
android:gravity="center_vertical"
|
||||
android:background="@android:color/holo_blue_light" />
|
||||
|
||||
<!-- Available peers -->
|
||||
<ListView
|
||||
android:id="@id/android:list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:drawSelectorOnTop="false" />
|
||||
|
||||
<TextView
|
||||
android:id="@id/android:empty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:layout_height="match_parent"
|
||||
android:text="@string/empty_message" />
|
||||
</LinearLayout>
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/linearLayout1"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
<fragment
|
||||
class="com.example.android.wifidirect.DeviceListFragment"
|
||||
android:id="@+id/frag_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/phone_list_height">
|
||||
<!-- Preview: layout=@layout/row_devices -->
|
||||
</fragment>
|
||||
<fragment
|
||||
class="com.example.android.wifidirect.DeviceDetailFragment"
|
||||
android:id="@+id/frag_detail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<!-- Preview: layout=@layout/device_detail -->
|
||||
</fragment>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="?android:attr/listPreferredItemHeight"
|
||||
android:background="?android:attr/activatedBackgroundIndicator"
|
||||
android:padding="6dip">
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_marginRight="2dip"
|
||||
android:src="@drawable/machine" />
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="fill_parent">
|
||||
<TextView
|
||||
android:id="@+id/device_name"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical" />
|
||||
<TextView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1"
|
||||
android:id="@+id/device_details"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/atn_direct_enable"
|
||||
android:icon="@drawable/ic_action_on_off"
|
||||
android:title="@string/enable_p2p_button"
|
||||
android:showAsAction="ifRoom|withText" />
|
||||
|
||||
<item
|
||||
android:id="@+id/atn_direct_discover"
|
||||
android:icon="@drawable/ic_action_discover"
|
||||
android:title="@string/discover_peers_button"
|
||||
android:showAsAction="ifRoom|withText" />
|
||||
</menu>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="status_bar_color">#FF000000</color>
|
||||
<color name="layout_border_color">#FF111111</color>
|
||||
</resources>
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2011 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<dimen name="tablet_list_width">300dp</dimen>
|
||||
<dimen name="phone_list_height">200dp</dimen>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">WiFi Direct</string>
|
||||
<string name="enable_p2p_button">P2P On/Off</string>
|
||||
<string name="discover_peers_button">Discover</string>
|
||||
<string name="connect_peer_button">Connect</string>
|
||||
<string name="disconnect_peer_button">Disconnect</string>
|
||||
<string name="get_file_button">Launch Gallery</string>
|
||||
<string name="empty"></string>
|
||||
<string name="yes">yes</string>
|
||||
<string name="no">no</string>
|
||||
<string name="client_text">This device will act as a client. Click on Gallery button to pick a local(stored) file</string>
|
||||
<string name="empty_message">No devices found. Turn on P2P and perform discovery from the Action Bar</string>
|
||||
<string name="p2p_off_warning">Enable P2P from action bar button above or system settings</string>
|
||||
<string name="group_owner_text">"Am I the Group Owner? "</string>
|
||||
<string name="label_me">ME</string>
|
||||
<string name="label_peers">PEERS</string>
|
||||
</resources>
|
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example.android.wifidirect;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.net.wifi.WpsInfo;
|
||||
import android.net.wifi.p2p.WifiP2pConfig;
|
||||
import android.net.wifi.p2p.WifiP2pDevice;
|
||||
import android.net.wifi.p2p.WifiP2pInfo;
|
||||
import android.net.wifi.p2p.WifiP2pManager.ConnectionInfoListener;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.example.android.wifidirect.DeviceListFragment.DeviceActionListener;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
/**
|
||||
* A fragment that manages a particular peer and allows interaction with device
|
||||
* i.e. setting up network connection and transferring data.
|
||||
*/
|
||||
public class DeviceDetailFragment extends Fragment implements ConnectionInfoListener {
|
||||
|
||||
protected static final int CHOOSE_FILE_RESULT_CODE = 20;
|
||||
private View mContentView = null;
|
||||
private WifiP2pDevice device;
|
||||
private WifiP2pInfo info;
|
||||
ProgressDialog progressDialog = null;
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
|
||||
mContentView = inflater.inflate(R.layout.device_detail, null);
|
||||
mContentView.findViewById(R.id.btn_connect).setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
WifiP2pConfig config = new WifiP2pConfig();
|
||||
config.deviceAddress = device.deviceAddress;
|
||||
config.wps.setup = WpsInfo.PBC;
|
||||
if (progressDialog != null && progressDialog.isShowing()) {
|
||||
progressDialog.dismiss();
|
||||
}
|
||||
progressDialog = ProgressDialog.show(getActivity(), "Press back to cancel",
|
||||
"Connecting to :" + device.deviceAddress, true, true
|
||||
// new DialogInterface.OnCancelListener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onCancel(DialogInterface dialog) {
|
||||
// ((DeviceActionListener) getActivity()).cancelDisconnect();
|
||||
// }
|
||||
// }
|
||||
);
|
||||
((DeviceActionListener) getActivity()).connect(config);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
mContentView.findViewById(R.id.btn_disconnect).setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
((DeviceActionListener) getActivity()).disconnect();
|
||||
}
|
||||
});
|
||||
|
||||
mContentView.findViewById(R.id.btn_start_client).setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// Allow user to pick an image from Gallery or other
|
||||
// registered apps
|
||||
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
intent.setType("image/*");
|
||||
startActivityForResult(intent, CHOOSE_FILE_RESULT_CODE);
|
||||
}
|
||||
});
|
||||
|
||||
return mContentView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
|
||||
// User has picked an image. Transfer it to group owner i.e peer using
|
||||
// FileTransferService.
|
||||
Uri uri = data.getData();
|
||||
TextView statusText = (TextView) mContentView.findViewById(R.id.status_text);
|
||||
statusText.setText("Sending: " + uri);
|
||||
Log.d(WiFiDirectActivity.TAG, "Intent----------- " + uri);
|
||||
Intent serviceIntent = new Intent(getActivity(), FileTransferService.class);
|
||||
serviceIntent.setAction(FileTransferService.ACTION_SEND_FILE);
|
||||
serviceIntent.putExtra(FileTransferService.EXTRAS_FILE_PATH, uri.toString());
|
||||
serviceIntent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_ADDRESS,
|
||||
info.groupOwnerAddress.getHostAddress());
|
||||
serviceIntent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_PORT, 8988);
|
||||
getActivity().startService(serviceIntent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionInfoAvailable(final WifiP2pInfo info) {
|
||||
if (progressDialog != null && progressDialog.isShowing()) {
|
||||
progressDialog.dismiss();
|
||||
}
|
||||
this.info = info;
|
||||
this.getView().setVisibility(View.VISIBLE);
|
||||
|
||||
// The owner IP is now known.
|
||||
TextView view = (TextView) mContentView.findViewById(R.id.group_owner);
|
||||
view.setText(getResources().getString(R.string.group_owner_text)
|
||||
+ ((info.isGroupOwner == true) ? getResources().getString(R.string.yes)
|
||||
: getResources().getString(R.string.no)));
|
||||
|
||||
// InetAddress from WifiP2pInfo struct.
|
||||
view = (TextView) mContentView.findViewById(R.id.device_info);
|
||||
view.setText("Group Owner IP - " + info.groupOwnerAddress.getHostAddress());
|
||||
|
||||
// After the group negotiation, we assign the group owner as the file
|
||||
// server. The file server is single threaded, single connection server
|
||||
// socket.
|
||||
if (info.groupFormed && info.isGroupOwner) {
|
||||
new FileServerAsyncTask(getActivity(), mContentView.findViewById(R.id.status_text))
|
||||
.execute();
|
||||
} else if (info.groupFormed) {
|
||||
// The other device acts as the client. In this case, we enable the
|
||||
// get file button.
|
||||
mContentView.findViewById(R.id.btn_start_client).setVisibility(View.VISIBLE);
|
||||
((TextView) mContentView.findViewById(R.id.status_text)).setText(getResources()
|
||||
.getString(R.string.client_text));
|
||||
}
|
||||
|
||||
// hide the connect button
|
||||
mContentView.findViewById(R.id.btn_connect).setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the UI with device data
|
||||
*
|
||||
* @param device the device to be displayed
|
||||
*/
|
||||
public void showDetails(WifiP2pDevice device) {
|
||||
this.device = device;
|
||||
this.getView().setVisibility(View.VISIBLE);
|
||||
TextView view = (TextView) mContentView.findViewById(R.id.device_address);
|
||||
view.setText(device.deviceAddress);
|
||||
view = (TextView) mContentView.findViewById(R.id.device_info);
|
||||
view.setText(device.toString());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the UI fields after a disconnect or direct mode disable operation.
|
||||
*/
|
||||
public void resetViews() {
|
||||
mContentView.findViewById(R.id.btn_connect).setVisibility(View.VISIBLE);
|
||||
TextView view = (TextView) mContentView.findViewById(R.id.device_address);
|
||||
view.setText(R.string.empty);
|
||||
view = (TextView) mContentView.findViewById(R.id.device_info);
|
||||
view.setText(R.string.empty);
|
||||
view = (TextView) mContentView.findViewById(R.id.group_owner);
|
||||
view.setText(R.string.empty);
|
||||
view = (TextView) mContentView.findViewById(R.id.status_text);
|
||||
view.setText(R.string.empty);
|
||||
mContentView.findViewById(R.id.btn_start_client).setVisibility(View.GONE);
|
||||
this.getView().setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple server socket that accepts connection and writes some data on
|
||||
* the stream.
|
||||
*/
|
||||
public static class FileServerAsyncTask extends AsyncTask<Void, Void, String> {
|
||||
|
||||
private Context context;
|
||||
private TextView statusText;
|
||||
|
||||
/**
|
||||
* @param context
|
||||
* @param statusText
|
||||
*/
|
||||
public FileServerAsyncTask(Context context, View statusText) {
|
||||
this.context = context;
|
||||
this.statusText = (TextView) statusText;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doInBackground(Void... params) {
|
||||
try {
|
||||
ServerSocket serverSocket = new ServerSocket(8988);
|
||||
Log.d(WiFiDirectActivity.TAG, "Server: Socket opened");
|
||||
Socket client = serverSocket.accept();
|
||||
Log.d(WiFiDirectActivity.TAG, "Server: connection done");
|
||||
final File f = new File(Environment.getExternalStorageDirectory() + "/"
|
||||
+ context.getPackageName() + "/wifip2pshared-" + System.currentTimeMillis()
|
||||
+ ".jpg");
|
||||
|
||||
File dirs = new File(f.getParent());
|
||||
if (!dirs.exists())
|
||||
dirs.mkdirs();
|
||||
f.createNewFile();
|
||||
|
||||
Log.d(WiFiDirectActivity.TAG, "server: copying files " + f.toString());
|
||||
InputStream inputstream = client.getInputStream();
|
||||
copyFile(inputstream, new FileOutputStream(f));
|
||||
serverSocket.close();
|
||||
return f.getAbsolutePath();
|
||||
} catch (IOException e) {
|
||||
Log.e(WiFiDirectActivity.TAG, e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see android.os.AsyncTask#onPostExecute(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected void onPostExecute(String result) {
|
||||
if (result != null) {
|
||||
statusText.setText("File copied - " + result);
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(android.content.Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(Uri.parse("file://" + result), "image/*");
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see android.os.AsyncTask#onPreExecute()
|
||||
*/
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
statusText.setText("Opening a server socket");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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) {
|
||||
Log.d(WiFiDirectActivity.TAG, e.toString());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example.android.wifidirect;
|
||||
|
||||
import android.app.ListFragment;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.net.wifi.p2p.WifiP2pConfig;
|
||||
import android.net.wifi.p2p.WifiP2pDevice;
|
||||
import android.net.wifi.p2p.WifiP2pDeviceList;
|
||||
import android.net.wifi.p2p.WifiP2pManager.PeerListListener;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A ListFragment that displays available peers on discovery and requests the
|
||||
* parent activity to handle user interaction events
|
||||
*/
|
||||
public class DeviceListFragment extends ListFragment implements PeerListListener {
|
||||
|
||||
private List<WifiP2pDevice> peers = new ArrayList<WifiP2pDevice>();
|
||||
ProgressDialog progressDialog = null;
|
||||
View mContentView = null;
|
||||
private WifiP2pDevice device;
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
this.setListAdapter(new WiFiPeerListAdapter(getActivity(), R.layout.row_devices, peers));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
mContentView = inflater.inflate(R.layout.device_list, null);
|
||||
return mContentView;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return this device
|
||||
*/
|
||||
public WifiP2pDevice getDevice() {
|
||||
return device;
|
||||
}
|
||||
|
||||
private static String getDeviceStatus(int deviceStatus) {
|
||||
Log.d(WiFiDirectActivity.TAG, "Peer status :" + 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";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate a connection with the peer.
|
||||
*/
|
||||
@Override
|
||||
public void onListItemClick(ListView l, View v, int position, long id) {
|
||||
WifiP2pDevice device = (WifiP2pDevice) getListAdapter().getItem(position);
|
||||
((DeviceActionListener) getActivity()).showDetails(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) getActivity().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;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update UI for this device.
|
||||
*
|
||||
* @param device WifiP2pDevice object
|
||||
*/
|
||||
public void updateThisDevice(WifiP2pDevice device) {
|
||||
this.device = device;
|
||||
TextView view = (TextView) mContentView.findViewById(R.id.my_name);
|
||||
view.setText(device.deviceName);
|
||||
view = (TextView) mContentView.findViewById(R.id.my_status);
|
||||
view.setText(getDeviceStatus(device.status));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPeersAvailable(WifiP2pDeviceList peerList) {
|
||||
if (progressDialog != null && progressDialog.isShowing()) {
|
||||
progressDialog.dismiss();
|
||||
}
|
||||
peers.clear();
|
||||
peers.addAll(peerList.getDeviceList());
|
||||
((WiFiPeerListAdapter) getListAdapter()).notifyDataSetChanged();
|
||||
if (peers.size() == 0) {
|
||||
Log.d(WiFiDirectActivity.TAG, "No devices found");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void clearPeers() {
|
||||
peers.clear();
|
||||
((WiFiPeerListAdapter) getListAdapter()).notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void onInitiateDiscovery() {
|
||||
if (progressDialog != null && progressDialog.isShowing()) {
|
||||
progressDialog.dismiss();
|
||||
}
|
||||
progressDialog = ProgressDialog.show(getActivity(), "Press back to cancel", "finding peers", true,
|
||||
true, new DialogInterface.OnCancelListener() {
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* An interface-callback for the activity to listen to fragment interaction
|
||||
* events.
|
||||
*/
|
||||
public interface DeviceActionListener {
|
||||
|
||||
void showDetails(WifiP2pDevice device);
|
||||
|
||||
void cancelDisconnect();
|
||||
|
||||
void connect(WifiP2pConfig config);
|
||||
|
||||
void disconnect();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
// Copyright 2011 Google Inc. All Rights Reserved.
|
||||
|
||||
package com.example.android.wifidirect;
|
||||
|
||||
import android.app.IntentService;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
|
||||
/**
|
||||
* A service that process each file transfer request i.e Intent by opening a
|
||||
* socket connection with the WiFi Direct Group Owner and writing the file
|
||||
*/
|
||||
public class FileTransferService extends IntentService {
|
||||
|
||||
private static final int SOCKET_TIMEOUT = 5000;
|
||||
public static final String ACTION_SEND_FILE = "com.example.android.wifidirect.SEND_FILE";
|
||||
public static final String EXTRAS_FILE_PATH = "file_url";
|
||||
public static final String EXTRAS_GROUP_OWNER_ADDRESS = "go_host";
|
||||
public static final String EXTRAS_GROUP_OWNER_PORT = "go_port";
|
||||
|
||||
public FileTransferService(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public FileTransferService() {
|
||||
super("FileTransferService");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see android.app.IntentService#onHandleIntent(android.content.Intent)
|
||||
*/
|
||||
@Override
|
||||
protected void onHandleIntent(Intent intent) {
|
||||
|
||||
Context context = getApplicationContext();
|
||||
if (intent.getAction().equals(ACTION_SEND_FILE)) {
|
||||
String fileUri = intent.getExtras().getString(EXTRAS_FILE_PATH);
|
||||
String host = intent.getExtras().getString(EXTRAS_GROUP_OWNER_ADDRESS);
|
||||
Socket socket = new Socket();
|
||||
int port = intent.getExtras().getInt(EXTRAS_GROUP_OWNER_PORT);
|
||||
|
||||
try {
|
||||
Log.d(WiFiDirectActivity.TAG, "Opening client socket - ");
|
||||
socket.bind(null);
|
||||
socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);
|
||||
|
||||
Log.d(WiFiDirectActivity.TAG, "Client socket - " + socket.isConnected());
|
||||
OutputStream stream = socket.getOutputStream();
|
||||
ContentResolver cr = context.getContentResolver();
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = cr.openInputStream(Uri.parse(fileUri));
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.d(WiFiDirectActivity.TAG, e.toString());
|
||||
}
|
||||
DeviceDetailFragment.copyFile(is, stream);
|
||||
Log.d(WiFiDirectActivity.TAG, "Client: Data written");
|
||||
} catch (IOException e) {
|
||||
Log.e(WiFiDirectActivity.TAG, e.getMessage());
|
||||
} finally {
|
||||
if (socket != null) {
|
||||
if (socket.isConnected()) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
// Give up
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example.android.wifidirect;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.wifi.p2p.WifiP2pConfig;
|
||||
import android.net.wifi.p2p.WifiP2pDevice;
|
||||
import android.net.wifi.p2p.WifiP2pManager;
|
||||
import android.net.wifi.p2p.WifiP2pManager.ActionListener;
|
||||
import android.net.wifi.p2p.WifiP2pManager.Channel;
|
||||
import android.net.wifi.p2p.WifiP2pManager.ChannelListener;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.example.android.wifidirect.DeviceListFragment.DeviceActionListener;
|
||||
|
||||
/**
|
||||
* An activity that uses WiFi Direct APIs to discover and connect with available
|
||||
* devices. WiFi Direct APIs are asynchronous and rely on callback mechanism
|
||||
* using interfaces to notify the application of operation success or failure.
|
||||
* The application should also register a BroadcastReceiver for notification of
|
||||
* WiFi state related events.
|
||||
*/
|
||||
public class WiFiDirectActivity extends Activity implements ChannelListener, DeviceActionListener {
|
||||
|
||||
public static final String TAG = "wifidirectdemo";
|
||||
private WifiP2pManager manager;
|
||||
private boolean isWifiP2pEnabled = false;
|
||||
private boolean retryChannel = false;
|
||||
|
||||
private final IntentFilter intentFilter = new IntentFilter();
|
||||
private Channel channel;
|
||||
private BroadcastReceiver receiver = null;
|
||||
|
||||
/**
|
||||
* @param isWifiP2pEnabled the isWifiP2pEnabled to set
|
||||
*/
|
||||
public void setIsWifiP2pEnabled(boolean isWifiP2pEnabled) {
|
||||
this.isWifiP2pEnabled = isWifiP2pEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.main);
|
||||
|
||||
// add necessary intent values to be matched.
|
||||
|
||||
intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
|
||||
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
|
||||
intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
|
||||
intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
|
||||
|
||||
manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
|
||||
channel = manager.initialize(this, getMainLooper(), null);
|
||||
}
|
||||
|
||||
/** register the BroadcastReceiver with the intent values to be matched */
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
receiver = new WiFiDirectBroadcastReceiver(manager, channel, this);
|
||||
registerReceiver(receiver, intentFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
unregisterReceiver(receiver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all peers and clear all fields. This is called on
|
||||
* BroadcastReceiver receiving a state change event.
|
||||
*/
|
||||
public void resetData() {
|
||||
DeviceListFragment fragmentList = (DeviceListFragment) getFragmentManager()
|
||||
.findFragmentById(R.id.frag_list);
|
||||
DeviceDetailFragment fragmentDetails = (DeviceDetailFragment) getFragmentManager()
|
||||
.findFragmentById(R.id.frag_detail);
|
||||
if (fragmentList != null) {
|
||||
fragmentList.clearPeers();
|
||||
}
|
||||
if (fragmentDetails != null) {
|
||||
fragmentDetails.resetViews();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.action_items, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
|
||||
*/
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.atn_direct_enable:
|
||||
if (manager != null && channel != null) {
|
||||
|
||||
// Since this is the system wireless settings activity, it's
|
||||
// not going to send us a result. We will be notified by
|
||||
// WiFiDeviceBroadcastReceiver instead.
|
||||
|
||||
startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
|
||||
} else {
|
||||
Log.e(TAG, "channel or manager is null");
|
||||
}
|
||||
return true;
|
||||
|
||||
case R.id.atn_direct_discover:
|
||||
if (!isWifiP2pEnabled) {
|
||||
Toast.makeText(WiFiDirectActivity.this, R.string.p2p_off_warning,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
}
|
||||
final DeviceListFragment fragment = (DeviceListFragment) getFragmentManager()
|
||||
.findFragmentById(R.id.frag_list);
|
||||
fragment.onInitiateDiscovery();
|
||||
manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
Toast.makeText(WiFiDirectActivity.this, "Discovery Initiated",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(int reasonCode) {
|
||||
Toast.makeText(WiFiDirectActivity.this, "Discovery Failed : " + reasonCode,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showDetails(WifiP2pDevice device) {
|
||||
DeviceDetailFragment fragment = (DeviceDetailFragment) getFragmentManager()
|
||||
.findFragmentById(R.id.frag_detail);
|
||||
fragment.showDetails(device);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(WifiP2pConfig config) {
|
||||
manager.connect(channel, config, new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
// WiFiDirectBroadcastReceiver will notify us. Ignore for now.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(int reason) {
|
||||
Toast.makeText(WiFiDirectActivity.this, "Connect failed. Retry.",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
final DeviceDetailFragment fragment = (DeviceDetailFragment) getFragmentManager()
|
||||
.findFragmentById(R.id.frag_detail);
|
||||
fragment.resetViews();
|
||||
manager.removeGroup(channel, new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void onFailure(int reasonCode) {
|
||||
Log.d(TAG, "Disconnect failed. Reason :" + reasonCode);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
fragment.getView().setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChannelDisconnected() {
|
||||
// we will try once more
|
||||
if (manager != null && !retryChannel) {
|
||||
Toast.makeText(this, "Channel lost. Trying again", Toast.LENGTH_LONG).show();
|
||||
resetData();
|
||||
retryChannel = true;
|
||||
manager.initialize(this, getMainLooper(), this);
|
||||
} else {
|
||||
Toast.makeText(this,
|
||||
"Severe! Channel is probably lost premanently. Try Disable/Re-Enable P2P.",
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelDisconnect() {
|
||||
|
||||
/*
|
||||
* A cancel abort request by user. Disconnect i.e. removeGroup if
|
||||
* already connected. Else, request WifiP2pManager to abort the ongoing
|
||||
* request
|
||||
*/
|
||||
if (manager != null) {
|
||||
final DeviceListFragment fragment = (DeviceListFragment) getFragmentManager()
|
||||
.findFragmentById(R.id.frag_list);
|
||||
if (fragment.getDevice() == null
|
||||
|| fragment.getDevice().status == WifiP2pDevice.CONNECTED) {
|
||||
disconnect();
|
||||
} else if (fragment.getDevice().status == WifiP2pDevice.AVAILABLE
|
||||
|| fragment.getDevice().status == WifiP2pDevice.INVITED) {
|
||||
|
||||
manager.cancelConnect(channel, new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
Toast.makeText(WiFiDirectActivity.this, "Aborting connection",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(int reasonCode) {
|
||||
Toast.makeText(WiFiDirectActivity.this,
|
||||
"Connect abort request failed. Reason Code: " + reasonCode,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example.android.wifidirect;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.wifi.p2p.WifiP2pDevice;
|
||||
import android.net.wifi.p2p.WifiP2pManager;
|
||||
import android.net.wifi.p2p.WifiP2pManager.Channel;
|
||||
import android.net.wifi.p2p.WifiP2pManager.PeerListListener;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* A BroadcastReceiver that notifies of important wifi p2p events.
|
||||
*/
|
||||
public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {
|
||||
|
||||
private WifiP2pManager manager;
|
||||
private Channel channel;
|
||||
private WiFiDirectActivity activity;
|
||||
|
||||
/**
|
||||
* @param manager WifiP2pManager system service
|
||||
* @param channel Wifi p2p channel
|
||||
* @param activity activity associated with the receiver
|
||||
*/
|
||||
public WiFiDirectBroadcastReceiver(WifiP2pManager manager, Channel channel,
|
||||
WiFiDirectActivity activity) {
|
||||
super();
|
||||
this.manager = manager;
|
||||
this.channel = channel;
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see android.content.BroadcastReceiver#onReceive(android.content.Context,
|
||||
* android.content.Intent)
|
||||
*/
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
|
||||
|
||||
// UI update to indicate wifi p2p status.
|
||||
int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
|
||||
if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
|
||||
// Wifi Direct mode is enabled
|
||||
activity.setIsWifiP2pEnabled(true);
|
||||
} else {
|
||||
activity.setIsWifiP2pEnabled(false);
|
||||
activity.resetData();
|
||||
|
||||
}
|
||||
Log.d(WiFiDirectActivity.TAG, "P2P state changed - " + state);
|
||||
} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
|
||||
|
||||
// request available peers from the wifi p2p manager. This is an
|
||||
// asynchronous call and the calling activity is notified with a
|
||||
// callback on PeerListListener.onPeersAvailable()
|
||||
if (manager != null) {
|
||||
manager.requestPeers(channel, (PeerListListener) activity.getFragmentManager()
|
||||
.findFragmentById(R.id.frag_list));
|
||||
}
|
||||
Log.d(WiFiDirectActivity.TAG, "P2P peers changed");
|
||||
} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
|
||||
|
||||
if (manager == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
NetworkInfo networkInfo = (NetworkInfo) intent
|
||||
.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
|
||||
|
||||
if (networkInfo.isConnected()) {
|
||||
|
||||
// we are connected with the other device, request connection
|
||||
// info to find group owner IP
|
||||
|
||||
DeviceDetailFragment fragment = (DeviceDetailFragment) activity
|
||||
.getFragmentManager().findFragmentById(R.id.frag_detail);
|
||||
manager.requestConnectionInfo(channel, fragment);
|
||||
} else {
|
||||
// It's a disconnect
|
||||
activity.resetData();
|
||||
}
|
||||
} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
|
||||
DeviceListFragment fragment = (DeviceListFragment) activity.getFragmentManager()
|
||||
.findFragmentById(R.id.frag_list);
|
||||
fragment.updateThisDevice((WifiP2pDevice) intent.getParcelableExtra(
|
||||
WifiP2pManager.EXTRA_WIFI_P2P_DEVICE));
|
||||
|
||||
}
|
||||
}
|
||||
}
|