Skip to content

Instantly share code, notes, and snippets.

@EXJUSTICE
Created January 4, 2017 07:30
Show Gist options
  • Save EXJUSTICE/25657f080131d4b14528983006fbf272 to your computer and use it in GitHub Desktop.
Save EXJUSTICE/25657f080131d4b14528983006fbf272 to your computer and use it in GitHub Desktop.
package com.xu.consent;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pDeviceList;
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.preference.PreferenceManager;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
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 java.util.ArrayList;
import java.util.List;
//Add in proper stamp callbacks when events take place
/**
Host Activity handling WIFI Direct, displaying two fragments along with listeners. Code will be explained
This should be the second activity, after loginActivity. Following this,
We would launch consentActivity
Unfourtuantely in its curent state, only clients can send info to GroupOwner
*A client can only begin a file transfer if it is not the P2P group owner. If the client
is the P2P owner, it cannot open a TCP socket since the Android WiFi direct API does not
provide a mechanism to retrieve the InetAddress (IP address) of any peer other than the
P2P group owner. This issue can be resolved upon finding a means to determine the IP
address of any given peer in the P2P group.
*/
public class WIFIDirectActivity extends AppCompatActivity implements ChannelListener, DeviceListFragment.DeviceActionListener {
public static final String TAG ="wifidirectdemo";
private WifiP2pManager manager;
private boolean isWifiP2pEnabled;
private boolean retryChannel = false;
private final IntentFilter intentFilter = new IntentFilter();
private Channel channel;
private BroadcastReceiver receiver =null;
public static String username;
SharedPreferences mPrefs;
boolean welcomeScreenShown;
boolean firstTime;
//instead of local ArrayList, we use a globalDB
public void setIsWifiP2pEnabled (boolean isWifiP2pEnabled){
this.isWifiP2pEnabled=isWifiP2pEnabled;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wifi);
//add necessary intent values to be matched with BroadcastReceiver
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);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//Fetch name first of our logged in user, will have to pass it to client as well
Intent fetchname = getIntent();
username = fetchname.getStringExtra("username");
//fetch singletoninstance, should be first instance for this particular situation
/*1. Initialize Manager and Channel. Manager needed to handle P2p and is called first,
Channel needed to connect to WIfi Direct Framework
All these details and activity reference needed for Registering with BroadCastReceiver
*/
manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
channel = manager.initialize(this, getMainLooper(), null);
//Check if first time running, inflate WelcomeFragment if necessary
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
// second argument is the default to use if the preference can't be found
welcomeScreenShown = mPrefs.getBoolean("welcomeShown", false);
firstTime = mPrefs.getBoolean("firstTimeWelcome", false);
if (!welcomeScreenShown && firstTime == true) {
// the code below will display a popup welcome screen
WelcomeFragment welcome = new WelcomeFragment();
welcome.show(this.getSupportFragmentManager(), "Welcome to HanGO");
}
}
@Override
public void onResume(){
super.onResume();
receiver = new WifiDirectBroadcastReceiver(manager, channel,this);
//Allow receiver to not only send info back to DirectActivity,
// but also have access to Wifi and channel stuff if needed
registerReceiver(receiver, intentFilter);
}
@Override
public void onPause(){
super.onPause();
unregisterReceiver(receiver);
}
//resetData method clears all fields, remove peers, called
//When BroadcastReceiver receives state change
public void resetData(){
//Find all frags first, written in XML
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();
}
}
//Handling option Menu inflation and calls
@Override
public boolean onCreateOptionsMenu (Menu menu){
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.action_items,menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.atn_direct_enable:
//Check first we have access to Wifi Manager and channel to access framework
if (manager != null && channel != null) {
/*Since this is android System wireless settings
Hence, we will not receive DIRECT result
Notification via WifiBroadCastReceiver instead
*/
startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
} else {
Log.e(TAG, "Channel or manager is null");
}
return true;
case R.id.atn_direct_discover:
//Clicked discover, initialize fragments and discover available peers
if (!isWifiP2pEnabled) {
Toast.makeText(WIFIDirectActivity.this, "WifiDirect is not enabled", 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();
//OnSuccess and DiscoverPeers are only to show that Discovery process is working
//Actual list of peers is done in broadcastReceiver:
//1. When System detects peers, Activity broadcasts WIFI_P2P_CHANGED_ACTION
//2. BroadCastReceiver receives intent, and calls requestPeers();
//3. Receiver displays all peers in listfragments
}
@Override
public void onFailure(int reasonCode) {
Toast.makeText(WIFIDirectActivity.this, "Discovery failed" + reasonCode, Toast.LENGTH_SHORT).show();
}
});
return true;
default:
return super.onOptionsItemSelected(item);
}
}
//WifiDirectActivity's ShowDetails is the initially called version, which forwards to fragments showDetails,
//Which does what?
@Override
public void showDetails(WifiP2pDevice device){
DeviceDetailFragment fragment = (DeviceDetailFragment)getFragmentManager().findFragmentById(R.id.frag_detail);
fragment.showDetails(device);
}
//Similiar to OnOptionsSelected's discoverPeers, we are usuing Managers connect to connect
//P2PConfig icnludes info on TARGET DEVICE
@Override
public void connect(WifiP2pConfig config){
manager.connect(channel, config, new ActionListener() {
@Override
public void onSuccess() {
//WifiDirectBroadcast will notify us
logconnect();
//For debugging
Intent startConsentActivity = new Intent(WIFIDirectActivity.this, ConsentActivity.class);
startActivity(startConsentActivity);
}
@Override
public void onFailure(int i) {
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();
/*
The device that creates the group,
becomes Group owner, which others can connect as clients
*/
//Cant initialize History fragment via same method since its not a part of WifiDirectActivity's XML,
//may have to create singleton DB class instead.
logdisconnect();
manager.removeGroup(channel, new ActionListener() {
@Override
public void onSuccess() {
//getView currently doesnt exist becaause fragment doesnt exist
fragment.getView().setVisibility(View.GONE);
}
@Override
public void onFailure(int reasonCode) {
Log.d(TAG,"Disconnect failed" +reasonCode);
}
});
}
//if channel disconnected, try again, if fail, then decalre lost
@Override
public void onChannelDisconnected(){
if (manager != null && !retryChannel){
Toast.makeText(this, "Channel lost, trying again",Toast.LENGTH_SHORT).show();
resetData();
retryChannel=true;
manager.initialize(this,getMainLooper(),this);
}else{
Toast.makeText(this,"error, try to renable p2p",Toast.LENGTH_SHORT).show();
}
}
@Override
public void cancelDisconnect(){
/* User actively aborts an connection attempt
if already connected, removeGroup
else, abort ongoing request through Manager
*/
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",Toast.LENGTH_SHORT).show();
}
public void onFailure(int reasonCode){
Toast.makeText(WIFIDirectActivity.this, "Abort failed" +reasonCode,Toast.LENGTH_SHORT).show();
}
});
}
}
logcancel();
}
public void logconnect(){
//maybe add in IPs later once w figure out wtf, passed through argument
//sdb.addStamp(new Stamp(System.currentTimeMillis(),"connection established"));
}
public void logdisconnect(){
//sdb.addStamp(new Stamp(System.currentTimeMillis(),"connection disconnected"));
}
public void logcancel(){
//sdb.addStamp(new Stamp(System.currentTimeMillis(),"connection cancelled by user"));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment