upload android base code part7

This commit is contained in:
August 2018-08-08 18:09:17 +08:00
parent 4e516ec6ed
commit 841ae54672
25229 changed files with 1709508 additions and 0 deletions

View 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))

View file

@ -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>

View 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>
&mdash; 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> &mdash; 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>
&mdash; 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>
&mdash; 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>
&mdash; 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>&lt;uses-sdk android:minSdkVersion="14" /&gt;</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>&lt;uses-sdk&gt;</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>&lt;uses-feature
android:name="android.hardware.wifi.direct" /&gt;</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>&lt;uses-feature&gt;</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>&lt;uses-feature&gt;</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" />

View file

@ -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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 646 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

View file

@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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;
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}
}
}
}
}
}

View file

@ -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();
}
});
}
}
}
}

View file

@ -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));
}
}
}