Tips & Tricks: WiFi Direct

Hi Android dev’s,

We are back in business at least on the website. We still are having some technical problems with our hardware.

Today we would like to share some information on WiFi Direct with Android.

What is WiFi Direct?
WiFi Direct is a direct connection between two WiFi devices, which at least one is WiFi Direct certified, without any access point in between. It can do peer to peer connections over WiFi, because it will start up an soft AP (Software Access Point). When the connection is established it can do similar things as bluetooth: share files, print files and play together. It has a larger range then bluetooth.

How to implement it in Android?
From Android 4.0 (API Level 14) it is possible to use WiFi Direct in applications.
Everything we need to do from within the application is coming from: WifiP2pManager. With WifiP2pManager you can do initialization, discover, connect and more.

To start you first need to add the following permissions to your Android manifest.

<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" />

After the right permissions are added you need to add a simple broadcast receiver, so your application will receive the events from the Android system.

/**
 * A BroadcastReceiver that notifies of important Wi-Fi p2p events.
 */
public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {
 
    private WifiP2pManager manager;
    private Channel channel;
    private MyWiFiActivity activity;
 
    public WiFiDirectBroadcastReceiver(WifiP2pManager manager, Channel channel,
            MyWifiActivity activity) {
        super();
        this.manager = manager;
        this.channel = channel;
        this.activity = activity;
    }
 
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
 
        if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
            int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
            if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
                // Wifi Direct is enabled
            } else {
                // Wi-Fi Direct is not enabled
            }
        } 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, myPeerListListener);
            }
        } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
            // Respond to new connection or disconnections
        } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
            // Respond to this device's wifi state changing
        }
    }
}

Then in your activity add the following:

WifiP2pManager mManager;
Channel mChannel;
BroadcastReceiver mReceiver;
...
@Override
protected void onCreate(Bundle savedInstanceState){
    ...
    mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
    mChannel = mManager.initialize(this, getMainLooper(), null);
    Receiver = new WiFiDirectBroadcastReceiver(manager, channel, this);
 
    mIntentFilter = new IntentFilter();
    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
    ...
}

Don’t forget to register and unregister the receiver in onResume() and onPause().

This is the first part you have to do, after this you can use the WifiP2pManager to discover peers and to connect to them.
This is done with the following code to discover peers:

manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
    @Override
    public void onSuccess() {
        ...
    }
 
    @Override
    public void onFailure(int reasonCode) {
        ...
    }
});

And for connecting to peers with the following code:

//obtain a peer from the WifiP2pDeviceList
WifiP2pDevice device;
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
manager.connect(channel, config, new ActionListener() {
 
    @Override
    public void onSuccess() {
        //success logic
    }
 
    @Override
    public void onFailure(int reason) {
        //failure logic
    }
});

We hope these tips and tricks will help you to start with WiFi Direct on Android.

Kind regards,
PullesSon – Android

Tips & Tricks: CalendarContract

Hi Android dev’s,

Like most of you already know: We got sauce! or in normal tems, Google released the source of Android 4.0 a.k.a. Ice Cream Sandwich (ICS). For more information see: http://source.android.com/.
This is the first version with code for tablets and phones. And with the source available the carriers and custom rom developers will roll out ICS soon.
That’s why today we will talk about a new feature in the SDK of ICS.

CalendarContract is the Calendar API for Android 4.0 (SDK 14) and up.

CalendarContract provides developers an interface for the calendar URI’s and data columns.

CalendarContract.Calendars:
This table holds the calendar specific information. Each row in this table contains the details for a single calendar, such as the name, color, sync info, etc.
CalendarContract.Events:
This table holds the event specific information. Each row in this table has the info for a single event. It contains information such as event title, location, start time, end time, etc. The event can occur one-time or can recur multiple times. Attendees, reminders, and extended properties are stored on separate tables and reference the _ID to link them with the event.
CalendarContract.Instances:
This table holds the start and end time for occurrences of an event. Each row in this table represents a single occurrence. For one-time events there will be a 1:1 mapping of instances to events. For recurring events, multiple rows will automatically be generated which correspond to multiple occurrences of that event.
CalendarContract.Attendees:
This table holds the event attendee or guest information. Each row represents a single guest of an event. It specifies the type of guest they are and their attendance response for the event.
CalendarContract.Reminders:
This table holds the alert/notification data. Each row represents a single alert for an event. An event can have multiple reminders. The number of reminders per event is specified in MAX_REMINDERS which is set by the Sync Adapter that owns the given calendar. Reminders are specified in minutes before the event and have a type.
CalendarContract.ExtendedProperties:
This table hold opaque data fields used by the sync adapter. The provider takes no action with items in this table except to delete them when their related events are deleted.

Add a new event to the calendar directly:

long startMillis = 0;
long endMillis = 0;
Calendar beginTime = Calendar.getInstance();
beginTime.set(2011, 11, 14, 16, 00);&nbsp;&nbsp;&nbsp;&nbsp;//year, month, day, hour, minute
startMillis = beginTime.getTimeInMillis();
Calendar endTime = Calendar.getInstance();
endTime.set(2011, 11, 14, 17, 00);&nbsp;&nbsp;&nbsp;&nbsp;//year, month, day, hour, minute
endMillis = endTime.getTimeInMillis();
 
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(CalendarContract.Events.DTSTART, startMillis);
values.put(CalendarContract.Events.DTEND, endMillis);
values.put(CalendarContract.Events.TITLE, "Ice Cream Sandwich Source Code Release");
values.put(CalendarContract.Events.DESCRIPTION, "Release the ICS source code, so all android followers are happy and will be busy with compiling their custom firmware base on the new source code.");
values.put(CalendarContract.Events.CALENDAR_ID, 3);
Uri uri = cr.insert(CalendarContract.Events.CONTENT_URI, values);

For this method you will need the permission: android.permission.READ_CALENDAR, if you don’t want extra permissions in your app, just launch a calendar intent with the event data.

To get a list of all the calendar event, just query Calendar.Events through the ContentResolver.

Regards,
PullesSon – Android

Tips & Tricks: AsyncTask.

Hi Android developers,

This week in tips and tricks: AsyncTask.

A AsyncTask is a class that provides you an easy interface to create a new thread. It is recommended to use it by background tasks, like downloading through a internet connection.
From Honeycomb (SDK API level 11) it’s even mandatory to use Asynctask’s for internet connection downloads and if it’s not done it will force close the application. So it will be also for Ice Cream Sandwich.
Besides it’s mandatory it’s also really handy. You will take pressure from the UI Thread and it will be processed faster and parallel to the UI Thread.

You have to start with:

private class DownloadFilesTask extends AsyncTask<void, void, void>

There are five methods to implement which are:
onPreExecute:
The first method called in the AsyncTask, called on the UI thread. In this method you usually prepare the progressbar, if needed.

@Override
protected void onPreExecute() {
    super.onPreExecute();
    showDialog(DIALOG_DOWNLOAD_PROGRESS);
}

doInBackground:
This is the method where is all the action. This method executes the time consuming tasks and publish the task progress, executed in background thread.

@Override
protected String doInBackground(String... params) {
    // perform Long time consuming operation
    return null;
}

onProgressUpdate
Method that updates the progress of the AsyncTask, run on the UI thread. This is where you update the progressbar.

@Override
protected void onProgressUpdate(String... progress) {
    mProgressDialog.setProgress(Integer.parseInt(progress[0]));
}

onPostExecute
The final method that gets called after doInBackground finishes, here we can update the UI with the results of the AsyncTask, like removing the progressbar.

@Override
protected void onPostExecute(String unused) {
    try {
        dismissDialog(DIALOG_DOWNLOAD_PROGRESS);
    } catch (Exception e){
        Log.e("APP_NAME","Unknown exception caught: " + e.getMessage());
    }
}

onCancelled
This method gets called if the AsyncTask.cancel() methods is called, terminating the execution of the AsyncTask.

@Override
protected void onCancelled() {
    dismissDialog(DIALOG_DOWNLOAD_PROGRESS);
}

To execute it just use:

new DownloadFilesTask().execute(param1, param2);

As you can see the AsyncTask is easy to implement and the methods are really easy to use and understand. It is highly recommended to use AsyncTask for task that doesn’t have to update the UI Thread.

We use AsyncTask in Let Me Android That For You and Perka’s File Stash.

For more information: http://developer.android.com/reference/android/os/AsyncTask.html

Regards,
PullesSon – Android