SHAREthem – Android library to simulate How SHAREit works

ic_launcherSHAREthem library makes File Sharing & Transfer a lot easier!!

Peer-to-Peer transfers are the best way to go when it comes to file sharing.

SHAREit App takes full advantage of it. I’ve seen many questions on StackOverFlow asking about how SHAREit works. (Just search shareit on SO and you’ll see a pageful of questions asking about the same thing). Well,  it’s easy to assume that they use Android Wi-Fi P2P libraries because android developer site says those libraries are used for P2P.

But, if you observe SHAREit app creates a Hotspot on receiver side which defeats the whole purpose of using Android P2P libraries and more over SHAREit works all the way from Android 2.2(at least it used to) where as Android P2P libraries works only on and above Android 4.0. May be they are using combination of both to take leverage of platform apis. But I’m gonna talk about Hotspot way since SHAREthem library is built around it.

That’s enough, tell me how it works 🙄

google-play-badge
Also app is posted on Playstore (Still in Beta). Click on the badge to see it action.

SHAREthem library facilitates file sharing and transfers using below components. Library also supports app to web sharing if receiver has no app installed :

  • Hotspot Controller
    HC uses Java Reflection since there are NO APIs available on Android for enabling/disabling Hotspots. Functionalities include:

    • Controller creates an OPEN Wifi hotspot configuration with an SSID which can intercepted by Receivers to recognize SHAREthem senders including port and sender names.
    • Restores user Hotspot-Configuration when Share mode is disabled
    • Provides a list of connected WiFi clients.
  • SHAREthem Server

A tiny HTTP server extended from NanoHttpd, serves the sender data to receivers using IP address as hostname and works on port assigned by user or system by default.

  • SHAREthem Service

Android service which manages lifecycle of SHAREthem-server and also handles foreground notification with stop action.

  • UI (Activities)
    Android activities to handle share/receive actions

    • Receiver – provides UI to list the files available to download. Posts a download request to Android Download Manager to start file downloads.
    • Sender – displays IP, Port & connected clients info along with file transfer status for each connected client(Receiver).

How to use it? Talk some code!!

I’ve made a DEMO App using SHAREthem library to demonstrate Sender & Receiver Modes. Demo Activity uses a nice library called android-filepicker for selecting files on Device.

Github link is included at the end of this article. Feel free to checkout.

 

Sender Mode:

To start Sender mode, you need to pass an array of strings holding references of files you want to share along with port(optional) and sender name using an Intent to start SHAREthemActivity

Intent intent = new Intent(getApplicationContext(), ShareActivity.class);
intent.putExtra(ShareService.EXTRA_FILE_PATHS, files);
intent.putExtra(ShareService.EXTRA_PORT, 52287);
intent.putExtra(ShareService.EXTRA_SENDER_NAME, "Sri");
startActivity(intent);

ShareService.EXTRA_FILE_PATHS: holds location references to local files on device.
In Sample app of Demo project on github i’ve used a nice looking File Explorer library to select files on device memory to share.
ShareService.EXTRA_PORT (optional): incase if you want to start SHAREserver on a specific port. Passing 0 or skipping this lets system to assign its own. One of the downside of letting system to do this is SSID may be not the same for a subsequent Sharing session. (PORT number is used in algorithm to generate SSID)
ShareService.EXTRA_SENDER_NAME (optional): used by Receiver to display connection information.

ShareActivity invokes SHAREService which in turn starts an instance of SHAREServer with device IP as wildcard address and port if unspecified assigned by system. On successful server setup, Hotspot Controller creates an OPEN WIfi Configuration with an SSID using combination of Android ID, Port number and Sender Name.

Activity scans for connected clients constantly using HotspotControl’s methods and adds them list as shown in below screenshots:

Receiver Mode:

Starting receiver mode is pretty simple as no intent extras needed. Receiver Activity starts scanning for senders automatically, you can turn off Receiver mode anytime though.

startActivity(new Intent(getApplicationContext(), ReceiverActivity.class));

Receiver scans for SHAREthem wifi based on naming convention used and fetches files information from SHAREthem server after successful connection. Here is the glance of Server method of server:

@Override
public Response serve(IHTTPSession session) {
    Response res = null;
    try {
        String url = session.getUri();
        Log.d(TAG, "request uri: " + url);
        if (TextUtils.isEmpty(url) || url.equals("/") || url.contains("/open"))
            res = createHtmlResponse();
        else if (url.equals("/status"))
            res = new NanoHTTPD.Response(Response.Status.OK, NanoHTTPD.MIME_PLAINTEXT, "Available");
        else if (url.equals("/apk"))
            res = createApkResponse(session.getHeaders().get("http-client-ip"));
        else if (url.equals("/logo") || url.equals("/favicon.ico"))
            res = createLogoResponse();
        else if (url.equals("/files"))
            res = createFilePathsResponse();
        else if (url.contains("/file/")) {
            int index = Integer.parseInt(url.replace("/file/", ""));
            if (index != -1)
                res = createFileResponse(m_filesTobeHosted[index], session.getHeaders().get("http-client-ip"));
        }
    } catch (Exception ioe) {
        ioe.printStackTrace();
        res = createErrorResponse(Response.Status.FORBIDDEN, ioe.getMessage());
    } finally {
        if (null == res)
            res = createForbiddenResponse();
    }
    res.addHeader("Accept-Ranges", "bytes");
    res.addHeader("Access-Control-Allow-Origin", "*");
    res.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
    return res;
}

Receiver activity embeds FilesListingFragment which is responsible for listing of Sender files and enqueue download request to Android Download Manager

Does it work on WEB browsers too?

Yes indeed. SHAREthem server serves an HTML file response which fires download requests upon selecting links. So all you need to do is key in

http://[ip]:[port]

on a web browser after connecting to hotspot. screen-shot-2017-01-09-at-11-42-31-pm

Nice. Any catches?

Yes, few

  • increasing targetSdkVersion version might impact behaviour of this library
    if targetSdkVersion >= 23
  • ShareActivity has to check for System Write permissions to proceed
  • Get Wifi Scan results method needs GPS to be ON and COARSE location permission.
  • library checks the targetSdkVersion to take care of above scenarios if targetSdkVersion > 20
  • If an application’s targetSdkVersion is LOLLIPOP or newer, network communication may not use Wi-Fi even if Wi-Fi is connected.
    this might impact when Receiver connectivity to SHAREthem hotspot, library checks for this scenario and prompts user to disable data
    For more info: https://developer.android.com/reference/android/net/wifi/WifiManager.html#enableNetwork(int, boolean)

Known issues??

  • On some devices with API level 21 and above, “`connectToOpenHotspot()“` method on WifiUtils disables other Wifi networks in-order to connect to SHAREthem WIfi Hotspot. Ideally increasing priority should be enough for making WifiConfiguration but recent Android version are making it hard for Wifi n.ws with no internet connectivity.
  • Enabling SHARE mode when System Wifi Hotspot is already active (enabled by user via Settings) might not work.

Troubleshooting

  • Receiver Connected but not able to display Sender info: As mentioned above, on API level 21 & above, n/w communication may not use Wifi with no internet access if MOBILE DATA has internet access. Library can prompt to disable MOBILE DATA if this scenario is met, but not yet implemented.
    So turn-off mobile to make Receiver work.
  • ReceiverActivity cannot connect to SHAREthem Wifi: Receiver tries to connect to SHAREthem Wifi in every way possible, but throws an error dialog if it fails. Dialog says to manually select SHAREthem Wifi on WIfi Settings.
    As a last resort, you can always manually connect to Sender Wifi.

Are you gonna give me Source Code??

Sure thing. Just remember that it is licensed under  Apache License Version 2.0 🙂

Github link: https://github.com/Sriharia/share-them

Please leave your feedback in comments. Thanks

Advertisements

HttpServer on Android to stream local video files to other devices

This blogs explains how to embed a mini HttpServer into your android app to serve local video files from your device to  other devices/desktop browsers/mediaplayers

You can do it by serving the local file using Java ServerSocket : server-side socket that waits for incoming client connections. A ServerSocket handles the requests and sends back an appropriate reply.

I made a demo App explaining this functionality, check out the code from Github (demo has a sample mp4, you can find it in assets folder. Move it your SD card  root folder to run the demo successfully)

device-2014-09-06-210137

LocalFileStreamingServer is a Thread which implements Runnable interface, you can create server object by passing the video file object from your activity. Continue reading