A P2P library for Android for discovery on local networks using UDP and transfer in general using TCP sockets

Overview

Near

Near is a P2P library which allows

  • Discovery like Android NSD, though with greater reliability and easier-to-use NearDiscovery API
  • Transfers among clients through an easy-to-use NearConnect API

Sample Usage

Usage Demo GIF

Sample app, with the source code here is available on PlayStore.

NearDiscovery

NearDiscovery takes hostname and a bunch of settings in a builder pattern for the discovery mechanism. A NearDiscovery object allows the following discovery related self-explanatory APIs:

  • void makeDiscoverable(String hostName, String mustMatch /* optional */);
  • void makeNonDiscoverable();
  • void startDiscovery();
  • void stopDiscovery();
  • Set<Host> getAllAvailablePeers();
  • boolean isDiscoverable();
  • boolean isDiscovering();

Here's how the NearDiscovery object is created

private NearDiscovery mNearDiscovery = new NearDiscovery.Builder()
                .setContext(this)
                .setDiscoverableTimeoutMillis(DISCOVERABLE_TIMEOUT_MILLIS)
                .setDiscoveryTimeoutMillis(DISCOVERY_TIMEOUT_MILLIS)
                .setDiscoverablePingIntervalMillis(DISCOVERABLE_PING_INTERVAL_MILLIS)
                .setDiscoveryListener(getNearDiscoveryListener(), Looper.getMainLooper())
                .setPort(8989) // optional
                .setFilter(Regex("filter")) // optional, use with makeDiscoverable("hostName", "filter")
                .build();

The Looper passed as the 2nd param of NearDiscovery.Builder.setDiscoveryListener() is for the thread on which the listener, the 1st param, should be called. Sample listener:

    @NonNull
    private NearDiscovery.Listener getNearDiscoveryListener() {
        return new NearDiscovery.Listener() {
            @Override
            public void onPeersUpdate(Set<Host> hosts) {
                // Handle updates of peer list here - some peer might have got removed if it wasn't reachable anymore or some new peer might have been added
            }

            @Override
            public void onDiscoveryTimeout() {
                // This is called after the discovery timeout (specified in the builder) from starting discovery using the startDiscovery()
            }

            @Override
            public void onDiscoveryFailure(Throwable e) {
                // This is called if discovery could not be started
            }

            @Override
            public void onDiscoverableTimeout() {
                // This is called after the discoverable timeout (specified in the builder) from becoming discoverable by others using the makeDiscoverable()
            }
        };
    }

NearDiscovery.Builder.setDiscoverablePingIntervalMillis() tells the interval at which each client broadcasts about its existence. The NearDiscovery.Listener.onPeersUpdate() gets called even if a peer is deemed stale, i.e. it's last broadcast received was more than twice the discoverable-ping-interval ago.

The discovery mechanism takes place in background services which do not hold any wakelocks.

NearConnect

A NearConnect object provides P2P mechanism with the following self-explanatory APIs:

  • long send(byte[] bytes, Host peer);
  • void startReceiving();
  • void stopReceiving(boolean abortCurrentTransfers);
  • Set<Host> getPeers();
  • boolean isReceiving();

NearConnect.startReceiving() only tells to start listening for any incoming transfers, similarly NearConnect.isReceiving() only tells if the client is listening for transfers or not and not if any data is currently being received. Here's how the NearConnect object is created:

        private NearConnect mNearConnect = new NearConnect.Builder()
                .fromDiscovery(mNearDiscovery)
                .setContext(this)
                .setListener(getNearConnectListener(), Looper.getMainLooper())
                .setPort(8990) // optional
                .build();

The NearDiscovery object passed in NearConnect.Builder.fromDiscovery() is only to get the list of peers from. Peers can be explicitly provided as well:

        private NearConnect mNearConnect = new NearConnect.Builder()
                .forPeers(peers) // Set<Host> peers
                .setContext(this)
                .setListener(getNearConnectListener(), Looper.getMainLooper())
                .setPort(8990) // optional
                .build();

Again, the NearConnect.Builder.setListener() takes the Listener as the 1st argument and the Looper on which to call the Listener as the 2nd argument. Here's what the Listener looks like:

    @NonNull
    private NearConnect.Listener getNearConnectListener() {
        return new NearConnect.Listener() {
            @Override
            public void onReceive(byte[] bytes, final Host sender) {
            // Process incoming data here
            }

            @Override
            public void onSendComplete(long jobId) {
            // jobId is the same as the return value of NearConnect.send(), an approximate epoch time of the send
            }

            @Override
            public void onSendFailure(Throwable e, long jobId) {
            // handle failed sends here
            }

            @Override
            public void onStartListenFailure(Throwable e) {
            // This tells that the NearConnect.startReceiving() didn't go through properly.
            // Common cause would be that another instance of NearConnect is already listening and it's NearConnect.stopReceiving() needs to be called first
            }
        };
    }

It's required to stop listening on a previous instance of NearConnect (using NearConnect.stopReceiving()) so as to start listening on another instance (by using NearConnect.startReceiving()). This is because the same server port is used in each instance (<- could be made configurable later if deemed necessary).

on startReceiving(), and on send() partial wakelocks are held and released on stopReceiving() and on send completion/failure respectively.

Note: NearConnect should work even outside of a local network, except across NAT firewalls.

Getting Started

Add jitpack.io to your root build.gradle

allprojects {
    repositories {
        ...
        maven { url "https://jitpack.io" }
    }
}

Then add the dependency in your project build.gradle

dependencies {
    ...
    implementation 'com.github.adroitandroid:Near:v2.0'
    ...
}

You can find the latest version here.

Limitations

  • File transfers aren't easy yet. Services are background, API to take notification to start them in foreground, and listener methods to publish updates are on the TODO list.
  • Current Min SDK is 19. Tested with multiple devices and because of code limitation.

License

View full license here. In short:

The MIT License is a permissive license that is short and to the point. It lets people do anything they want with your code as long as they provide attribution back to you and don’t hold you liable.

Comments
  • Pure Java Equivalent

    Pure Java Equivalent

    I need a pure Java equivalent for Desktop applications But I'm running into some problems implementing this (especially implementing the server)

    It would be very cool if you took care of it and created a repository for it. I would of course also help as much as possible if it is difficult in terms of time.

    opened by DATL4G 4
  • Upgrade minSdkVersion& add the possibility to have mutiple instance of NearConnection

    Upgrade minSdkVersion& add the possibility to have mutiple instance of NearConnection

    Upgrade the minSdkversion to 26 Add the possibility to set a port to an NearConnection to have multiple instance running #2 set minsdkversion to 19 (tested on multiple devices)

    opened by AndroFlo 4
  • Crashes app after going to background

    Crashes app after going to background

    OnPause of my activity I do:

        if (nearDiscovery.isDiscovering) {
          nearDiscovery.stopDiscovery()
        }
        if (nearDiscovery.isDiscoverable) {
          nearDiscovery.makeNonDiscoverable()
        }
        if (nearConnect.isReceiving) {
          nearConnect.stopReceiving(false)
        }
    

    but still it crashes with this error:

    java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter intent         at com.adroitandroid.near.connect.server.TcpServerService.onStartCommand(TcpServerService.kt)
    
    opened by ANPez 2
  • >2 devices and host/peer setup

    >2 devices and host/peer setup

    Hi there,

    Firstly, thank you for the fantastic job you've done with this API! It's made P2P vastly simpler and cleaner for me. I would like to make use of the API for a project I am working on - notably, a game involving up to 5 devices, with one 'host' device and four peer users. The peer users will need to send data to the host, and the host will have to send data out to all peer users.

    I have seen the API used effectively in your sample app for two-way communication - for more users, is it as simple as opening up the discovery process again on a designated 'host' device? I.e. can one device maintain active connections with multiple devices and be able to send out messages that are picked up by them all?

    Thanks!

    opened by layton322 2
  • Out Of Memory

    Out Of Memory

    Hello,

    I have this error sometimes.

    Fatal Exception: java.lang.OutOfMemoryError: pthread_create (stack size 16384 bytes) failed: Try again at java.lang.VMThread.create(VMThread.java) at java.lang.Thread.start(Thread.java:1029) at com.adroitandroid.near.connect.TcpServerService.onNewReceive(TcpServerService.java:131) at com.adroitandroid.near.connect.TcpServerService.access$300(TcpServerService.java:25) at com.adroitandroid.near.connect.TcpServerService$1$1.run(TcpServerService.java:81) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:136) at android.os.HandlerThread.run(HandlerThread.java:61)

    opened by AndroFlo 2
  • java.lang.NoClassDefFoundError

    java.lang.NoClassDefFoundError

    java.lang.NoClassDefFoundError: Failed resolution of: Lkotlin/text/Regex; what is the cause for this error?

    Code is below mNearDiscovery = new NearDiscovery.Builder() .setContext(this) .setDiscoverableTimeoutMillis(60000) .setDiscoveryTimeoutMillis(60000) .setDiscoverablePingIntervalMillis(1000) .setDiscoveryListener(getNearDiscoveryListener(), Looper.getMainLooper())

                .build();
        mNearDiscovery.makeDiscoverable("Abcd","");
    
    opened by jobayerjim9 0
  • IllegalArgumentException when I exit

    IllegalArgumentException when I exit

    I ran your example and when I exit the app this error appears:

        java.lang.RuntimeException: Unable to start service com.adroitandroid.near.discovery.client.UdpBroadcastService@73c0f23 with null: java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkNotNullParameter, parameter intent
            at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3449)
            at android.app.ActivityThread.-wrap21(ActivityThread.java)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1633)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:154)
            at android.app.ActivityThread.main(ActivityThread.java:6316)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:872)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:762)
         Caused by: java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkNotNullParameter, parameter intent
            at com.adroitandroid.near.discovery.client.UdpBroadcastService.onStartCommand(UdpBroadcastService.kt)
            at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3432)
            at android.app.ActivityThread.-wrap21(ActivityThread.java) 
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1633) 
            at android.os.Handler.dispatchMessage(Handler.java:102) 
            at android.os.Looper.loop(Looper.java:154) 
            at android.app.ActivityThread.main(ActivityThread.java:6316) 
            at java.lang.reflect.Method.invoke(Native Method) 
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:872) 
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:762) 
    

    This happens on android 7, on android 10 everything is ok. I need some help. Thanks

    opened by vankad24 3
  • Stop after mServerSocket!!.accept()

    Stop after mServerSocket!!.accept()

    Hii, I am just creating a demo exactly like yours. But I got an issue with the socket object. Every time it stops in the startServer method(val connectionSocket = mServerSocket!!.accept()) and it display "Collecting data" in debuging. Capture Capture1

    opened by n-flow 2
  • Can makeDiscoverable by service like NSD?

    Can makeDiscoverable by service like NSD?

    I have a lot of devices and I want to group them by service, can you do it? ex: makeDiscoverable (String hostName, String serviceName);

    makeDiscoverable ("My android device", "printer.tcp");

    Look for devices that have the "printer.tcp" service registered instead of searching for them all startDiscovery ("printer.tcp")

    opened by hienlt0610 2
Releases(v2.0)
  • v2.0(May 4, 2020)

    Kotlin Migration

    Extremely helpful for Kotlin applications and almost no change for Java apps

    Added ConnectivityOberver

    Necessary because ConnectivityManager.CONNECTIVITY_ACTION is deprecated

    Additional Features

    Added the possibility to set the port for UDP and TCP, so you can find e.g. only devices that use the same port

    Filters can be added to e.g. only find devices that contain a certain string

    val nearDiscovery = NearDiscovery.Builder()
    .setContext(this)
    .setDiscoverableTimeoutMillis(DISCOVERABLE_TIMEOUT_MILLIS)
    .setDiscoveryTimeoutMillis(DISCOVERY_TIMEOUT_MILLIS)
    .setDiscoverablePingIntervalMillis(DISCOVERABLE_PING_INTERVAL_MILLIS)
    .setDiscoveryListener(getNearDiscoveryListener(), Looper.getMainLooper())
    .setPort(8989) // optional
    .setFilter(Regex("filter")) // optional
    .build()
    
    nearDiscovery.makeDiscoverable("hostName", "filter" /* optional */)
    

    This will listen on Port 8989 and will show only Hosts specified the filterText "filter"

    • If you set a Filter on nearDiscovery but not setting a filterText, the Host will not be found
    • The other way around neither
    • If you don't specify a filter and filterText then all Hosts will be found

    Credits

    This release is entirely thanks to @DATL4G

    Source code(tar.gz)
    Source code(zip)
  • v1.2(Oct 1, 2019)

    • updated gradle version
    • replaced deprecated support libs with androidx
    • updated other libs
    • set minSdk to 19
    • added annotations
    • updated gitignore
    Source code(tar.gz)
    Source code(zip)
  • v1.1.1(Jun 29, 2017)

Android app to search for artists, albums or tracks and get a list of related songs using the iTunes Searcher API.

iTunes Searcher Android app to search for artists, albums or tracks and get a list of related songs using the iTunes Searcher API. Each song may be cl

Miguel Freitas 2 Oct 19, 2022
This app includes Implementation of Huawei and Google Kits in a single codebase using Build Variants. 🗺 📩

Build Variant App ?? ?? ?? Build variant is a feature of Android Studio to create a project which can be build in different versions. By using Build V

Halil Özel 13 May 26, 2022
This is a Bluetooth operational Chat-App developed using Kotlin which shows the list of available devices nearby and paired devices, upon clicking you can start chat

This is a Bluetooth operational Chat-App developed using Kotlin which shows the list of available devices nearby and paired devices, upon clicking you can start chat ... VOILA ???? It is still in its early stages of development and currently let user to one-time chat at a time. It is under heavy development ??

Shalu Ambasta 3 Jan 10, 2022
Chat App is built to demonstrate a simple end-to-end chat encryption using RSA and AES algorithms

End-to-End Encrypted Chat ?? Chat App is built to demonstrate a simple end-to-end chat encryption using RSA and AES algorithms Built With ⚒️ Jetpack C

Team Matrix 6 Dec 23, 2022
A simple library for creating animated warnings/dialogs/alerts for Android.

Noty A simple library for creating animated warnings/notifications for Android. Examples Show me code Show me code Show me code Show me code Show me c

Emre 144 Nov 29, 2022
An Android library for simple notification displayed inside ViewGroup instead of system.

SimpleNotificationBar SimpleNotificationBar is an Android library that helps developers to easily create a Notification inside a view group, instead o

Tristan Le 2 Jul 29, 2022
💙 Android sample Avengers chat application using Stream Chat SDK based on MVVM (ViewModel, Coroutines, Room, Hilt, Repository) architecture.

Avengers Chat AvengersChat is a demo application based on modern Android tech stacks and Stream Chat SDK. Previews Download Go to the Releases to down

Jaewoong Eum 352 Dec 25, 2022
Firebase-Chat-App-Final - An android real-time chat application implemented using firebase

Firebase-Chat-App-Final An android real-time chat application implemented using

Tanmay Nandanikar 4 Sep 10, 2022
A simple real-time chatting application using android

In this project we have created a simple real-time chatting application using android. In this project we can chat with a registered user in the app. We can also set profile photo, about, name. After chatting with registered user we can also logout from the app and we can login, whenever we want .

Shankar Karande 3 Sep 26, 2022
A chat app for Android written in Kotlin using MVVM.

Chat App Android About A chat app for Android written in Kotlin using MVVM. Features Authentication: Email and password Google Auth Reset Password Sen

Sreshtha Mehrotra 14 Jul 3, 2022
A chat app for Android written in Kotlin using MVVM.

Chat App Android About A chat app for Android written in Kotlin using MVVM. Features Authentication: Email and password Google Auth Reset Password Sen

Sreshtha Mehrotra 14 Jul 3, 2022
SayHi! is an instant messaging app that allows users to send text messages to other people using the app

SayHi SayHi! is an instant messaging app that allows users to send text messages to other people using the app ?? Screen Shots ?? Features OTP Verific

Prince Fahad 0 Dec 25, 2021
Quick Text is about send the message on WhatsApp without saving number. You can see the status of other and share and download those status also.

Quick Text is about send the message on WhatsApp without saving number. You can see the status of other and share and download those status also.

Dheeraj Gupta 11 May 25, 2022
Messaging API: Connect to PostgreSQL and Kafka to obtain and manage cars inventory

Messaging-API In this simple API, we connect to PostgreSQL and Kafka to obtain a

Kevork 0 Feb 18, 2022
A simple video calling application uses Firebase database and WebRTC API that enables you Peer-to-Peer Full-HD video and audio connection.

A simple video calling application uses Firebase database and WebRTC API that enables you Peer-to-Peer Full-HD video and audio connection.

Indrajit Sahu 10 Sep 27, 2022
Android has a built in microphone through which you can capture audio and store it , or play it in your phone. There are many ways to do that but with this dialog you can do all thats with only one dialog.

# Media Recorder Dialog ![](https://img.shields.io/badge/Platform-Android-brightgreen.svg) ![](https://img.shields.io/badge/Android-CustomView-blue.sv

Abdullah Alhazmy 73 Nov 29, 2022
Open Source Messenger App For Android - Real-time Messaging, Voice and Video Calls

Open Source Messenger App For Android - Real-time Messaging, Voice and Video Calls

mesibo 630 Dec 7, 2022
A hybrid chat android application based on the features of Instagram and Whatsapp having UI just as Telegram.

A hybrid chat android application based on the features of Instagram and Whatsapp having UI just as Telegram.

Ratik Tiwari 1 May 22, 2022
AvengersChat is a demo application based on modern Android tech stacks and Stream Chat SDK.

?? Android sample Avengers chat application using Stream Chat SDK based on MVVM (ViewModel, Coroutines, Room, Hilt, Repository) architecture.

Stream 352 Dec 25, 2022