Remoter - An alternative to Android AIDL for Android Remote IPC services using plain java interfaces

Overview

Remoter

Remoter - An alternative to Android AIDL for Android Remote IPC services using plain java interfaces

Remoter makes developing android remote services intuitive without messing with AIDL.

Android IPC through AIDL

Android supports remote IPC using AIDL. This process of using "aidl" is painful and limited.

Some of the problems and limitations of AIDL are :

  • Unlike the intuitive way of defining an inteface defintions as an interface, AIDL forces you to define the interface in an ".aidl" file
  • The .aidl file is usually in a different folder than your normal source
  • You lose most of the IDE capability for the ".aidl"
  • You can't use an existing interface class and convert that to a remote interface -- it has to be defined seperately as ".aidl"
  • Only limited predefined data types are supported in aidl
  • Any custom Parcelable class that you want to pass through the interface has to be defined again as another ".aidl" file!
  • No overloaded methods!- Methods with same name fail
  • Can't extend an aidl with another
  • Can't throw custom exceptions

Remoter - An intuitive way for Android IPC

Remoter solves the above problems in AIDL by allowing you to define the remote interface using plain java interface, and implement it using plain java implementation of the interface.

All you have to do is annotate the interface using @Remoter

@Remoter
public interface ISampleService {
    ...
}
  • No messy .aidl, just plain simple interface
  • Implement the interface directly using intuitive normal java way, instead of extending Stub
  • Fully interoperable with AIDL. Remoter creates the same serialized data as created by AIDL, so it is fully interoperable with AIDL
  • Supports more data types than AIDL, everything supported by Parceler
  • Make an interface that extends other interfaces as @Remoter
  • Interface methods can throw any exceptions. Clients will get the same exception that is thrown.
  • Remoter interface can be templated
  • Remoter is an annotation processor that generates two helper classes during build time -- a client side Proxy and a service side Stub that allows you to wrap your interface and implementation
  • Support kotlin coroutines!

At the client side

  • Simply wrap the binder that you got from the ServiceConnection with the autogenerated Proxy for your interface
ISampleService sampleService = new ISampleService_Proxy( binder );

At the service side

  • Wrap the implementation with the autogenerated Stub to covert it as a remote Binder and return that from your service
Binder binder = new ISampleService_Stub( sampleServiceImpl );

That's it!

Annotations

  • @Remoter Annotate on an interface to make it a remote interface
  • @ParamIn Mark an array or Parcelable parameter as an input only parameter(in of aidl). By default they are input and output (inout of aidl)
  • @ParamOut Mark an array or Parcelable parameter as an output only parameter(out of aidl).
  • @Oneway Annotate on a method (in the @Remoter interface) with void return to make it an asynchronous method.
  • @NullableType Used to annotate a type parameter or suspend function return as nullable. See below for more details

Kotlin Support with suspend functions

Remoter supports Kotlin interfaces with suspend functions. If your interface (marked with @Remoter) has any suspend functions, then the generated Proxy and Stub will be in Kotlin, enabling to call your remoter service method from coroutines.

  • The suspend functions will be dispatched using the Dispatcher.IO context
  • Kotlin Proxy can be created using the optional constructor that accepts IServiceConnector which moves service connection to a suspendable coroutine
Kotlin Example
  • Define interface in kotlin as suspend
@Remoter
interface ISampleService {

    /**
     * A suspend function which will be implemented by a service
     */
    suspend fun authenticate(userName:String, password:String) : Boolean
}
  • Include the depednecy for RemoterBuilder to take advantage of suspended service connection
implementation 'com.josesamuel:remoter-builder:<VERSION>'
  • From your coroutine, call the remote service call as follows
//From your coroutine context - 

//create service using serviceintent
val service = ISampleService_Proxy(context, SERVICE_INTENT)

//call the suspend function
val authenticated = service.authenticate(userName, password)

//The above call will 
 - suspend the current context
 - connect to service, 
 - make the remote call, 

 all sequentially without blocking the calling thread!
 
  • No need to take care of service connection!
  • No need to move to background thread for service call and then to main thred to update UI!
Notes on Kotlin support
  • Add remoter-builder dependency to get support for suspendable service connection using IServiceConnector
  • vararg is not supported. Either use array or non suspend
  • If any return is nullable type on a suspend function, explicitly mark the method with @NullableType
  • If any types in a generic parameter is nullable, explicitly mnark those parameter with @NullableType optionally specifying which indexex of that type parameter are nullable

Getting Remoter

Gradle dependency

dependencies {

    implementation 'com.josesamuel:remoter-annotations:2.0.2'
    kapt 'com.josesamuel:remoter:2.0.2'
    
    
    //If using kotlin coroutines, include following 
    //to make even the service connection simpler - 
    
    implementation 'com.josesamuel:remoter-builder:2.0.2'
    
}

License

Copyright 2017 Joseph Samuel

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.
Comments
  • Allow code generation for foreign interfaces.

    Allow code generation for foreign interfaces.

    I have a multiplatform project (desktop and android) with a hierarchy of modules.

    at the base is a plain Java library written in Kotlin. (:businesslogic) It contains an interface definition. (IBusinessLogic)

    I then have an android library module that depends on this .jar, (:businesslogic:android) where I need to create a remoter host service and a client for this interface.

    I can add com.josesamuel:remoter-annotations to the Java Library module (:businesslogic) and annotate the interface, but since it is a pure java library with no Android dependency (it produces a .jar, not an .aar) I cannot add com.josesamuel:remoter-builder and have a remoter stub or proxy generated in that module.

    I would like to keep the interface defined in the Java module (:businesslogic) so as to have all the business logic separate from the android platform.

    would it be possible to add some kind of mechanism to have the remoter-builder generate an implementation for the interface (IBusinessLogic) in the android module? (:businesslogic:android) while keeping the interface in the java module? Perhaps this could apply to any interface, not just ones that are marked with @Remoter?

    perhaps something like the marker you have in your suspender library?

    @GenerateRemoterFor(classesToWrap = [
        IBusinessLogic::class, 
        IThirdPartyLibraryInterface::class
    ])
    interface XXX
    
    opened by Flockavelli 16
  • How to call setStubProxyCheck on a listener.

    How to call setStubProxyCheck on a listener.

    Hi came across an issues. I am testing your library for communication between 2 different apps and at one point I have added extra methods to my listener on de server app and notice the crash because client app had the old version of the listener.

    I cannot seem to find how to get instance of each listener as _stub and set setStubProxyCheck(false) on them.

    As in your examples I have registerListener(listener: IRemoteServiceListener) Remoter interface implementation.

    Where would get access to instance of IRemoteServiceListener_Stub?

    opened by NLLAPPS 6
  • Accessing AIDL file

    Accessing AIDL file

    Is it possible to access the AIDL file that remoter generates from my kotlin interface?

    I would like to have access to it so that I can feed it into the Xamarin Android AIDL compiler so that I can have the service be implemented in C#.

    opened by Volatile-Memory 2
  • package org.parceler does not exist

    package org.parceler does not exist

    Hi! Great library.

    Just encountered this issue when using remoter for a kotlin interface. I included the library using a kapt annotation processor:

    implementation 'com.josesamuel:remoter-annotations:1.2.4'
    kapt 'com.josesamuel:remoter:1.2.4'
    

    The annotation processor runs correctly and generates my proxy and stub, but at compile time throws the error package org.parceler does not exist whenever the generated stub tries to call org.parceler.Parcels.wrap().

    Adding the following to my build.gradle works around the issue, but shouldn't Parceler be a transitive dependency?

    implementation 'org.parceler:parceler-api:1.1.12'
    kapt 'org.parceler:parceler:1.1.12'
    
    opened by y-a-n-n 2
  • Does not work w/ Parcelize

    Does not work w/ Parcelize

    Parcelize itself does not generate an accessible CREATOR or writeToParcel in kotlin. For the CREATOR, technically you can create a java helper method to access the CREATOR accessible from the java side, however, I need to look further into the writeToParcel side.

    opened by herriojr 1
  • Unchecked Exception is swallowed on oneway communication

    Unchecked Exception is swallowed on oneway communication

    Issue description

    Lets assume we two apps, one acts as Server and the other acts as Client for a IPC Oneway call. Now the Client performs a Oneway IPC call which includes a callback to the Server. The Server tries to process the request and suddenly produces a unchecked exception (OutOfMemory...). The Remoter Framework is now swallowing the unchecked Exception and the Client still waits for the callback to be called.

    Steps to reproduce the issue

    1. Client calls Server via Oneway call
    2. Server produces unchecked exception
    3. Remoter swallows exception and Server continues

    What's the expected result?

    Unchecked exception in case of a IPC oneway call should be thrown which leads to the death of the App.

    What's the actual result?

    We had a OutOfMemory on the Server side and remoter was the cause that Android wasn't restarting our App because the OutOfMemory wasn't propagated any further. Instead the App got stuck in a unusable state.

    opened by St3ffn 1
  • Fix parameter collisions

    Fix parameter collisions

    I had the problem that methods with a parameter called data would not compile, because remoter uses that name in the proxy.

    I fixed that by renaming all parameters in the proxy. Unfortunalety, that required changes in all ParamBuilders.

    opened by F43nd1r 1
  • Communication between 2 apps

    Communication between 2 apps

    Hi, thank you for great work. I was wondering how one would go about having 2 apps communicating with your library. You samples seems to show only within communication within app on a different process.

    I am trying to have 2 apps, signed with same signature one as server and another as client communication with remoter. Is it possible at all?

    opened by NLLAPPS 0
  • is It possible user Remoter service in bindDeviceAdminServiceAsUser of the DevicePolicyManager?

    is It possible user Remoter service in bindDeviceAdminServiceAsUser of the DevicePolicyManager?

    Hi, my solution uses multiples users on android and I have an AIDL server running on the owner user where the other users access it, I found this library and it would be perfect for new architecture that I'm implementing, but to access a service on another user is necessary bindAdminDeviceServiceAsUser, is it possible to ultiliza somehow? Or have any other suggestions?

    opened by franklinwesley 4
Releases(v2.0.0)
Owner
Joseph Samuel
Joseph Samuel
Android Swipeable button like in iOS unlock screen. Made by Stfalcon

swipeable-button Who we are Need iOS and Android apps, MVP development or prototyping? Contact us via [email protected]. We develop software since 200

Stfalcon LLC 86 Nov 29, 2022
Demo app to showcase Sensor data using AIDL bound services.

AIDLServices Displays data related to TYPE_ROTATION_VECTOR sensor using AIDL Consist of aidlsdk module that expose sensor data Sample app to show the

Vikas Mane 3 May 26, 2021
A Kotlin library for interacting with Discord via IPC

KDiscordIPC A Kotlin library for interacting with Discord via IPC Features Fully documented codebase macOS and Linux support (including M1 Macs, Windo

Conor Byrne 17 Dec 14, 2022
Project with AIDL, LifecycleService, CustomView

Digital Speedometer Project, where speed values are generated in background in the Service (SpeedValuesService). Then values are sent to Activity (Mai

Melkonian Nataliia 0 Dec 24, 2021
POC Simulate Backend Biometric Authentication with AIDL (client app/server app)

poc-simulate-bio-auth-aidl POC Simulate Backend Biometric Authentication with AIDL (client app/server app) #How to use Install server app and run Inst

gundamD 0 Dec 30, 2021
Urban Lore is an app for adventurers who appreciate the hidden gems hiding in plain sight.

Urban Lore Urban Lore is an app for adventurers who appreciate the hidden gems hiding in plain sight. Visit various places and discover their backstor

Jurij Dolenc 3 Jul 18, 2022
pokestack is an all-in-one solution for mobile voice interfaces on Android.

Extensible Android mobile voice framework: wakeword, ASR, NLU, and TTS. Easily add voice to any Android app!

Spokestack 57 Nov 20, 2022
Fragments: Advanced Reusable Interfaces on Android

LIVE #016 - Fragments: Interfaces reutilizáveis avançadas no Android (Atualizado com Jetpack) Código fonte do projeto criado na live #016, ensinando c

Kaique Ocanha 6 Oct 3, 2022
Practica con Jetpack Compose en Android, creando interfaces de mejor calidad.

Food Delivery UI - Jetpack Compose Food Delivery UI on Android using Jetpack Compose. This project is a starting point for a Android application. Cred

Bolivar Cortes 6 Nov 14, 2022
ConfigurNation - Annotation based Kotlin Interfaces for Android SharedPreferences

ConfigurNation Annotation based Kotlin Interfaces for Android SharedPreferences Installation Gradle Dependencies implementation 'com.izikode.izilib:co

Fanis Veizis 4 Jan 19, 2019
🎲 Kotlin Symbol Processor to auto-generate extensive sealed classes and interfaces for Android and Kotlin.

SealedX ?? Kotlin Symbol Processor to auto-generate extensive sealed classes and interfaces for Android and Kotlin. Why SealedX? SealedX generates ext

Jaewoong Eum 236 Nov 30, 2022
Jetpack Compose for Desktop and Web, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.

Jetpack Compose for Desktop and Web, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.

JetBrains 10k Jan 7, 2023
Simple Kotlin application that displays the currently available network interfaces on your machine

Network-Interface-Checker Simple Kotlin application that displays the currently available network interfaces on your machine. An executable jar can be

Joshua Soberg 3 Jun 10, 2022
A pair of applications provide a direct means of integrating with one another via application programming interfaces (APIs)

What is a native integration? It's when a pair of applications provide a direct means of integrating with one another via application programming interfaces (APIs). Once integrated, data can flow between the apps and become more readily available to your employees.

Behruz Hurramov 2 Jan 17, 2022
Gradle plugin to check, if rest-controllers are used by clients and clients have suitable rest-interfaces

Verify-Feign Gradle Plugin This plugin will help you to verify all rest-clients and -controllers in a multimodule spring project. It will check, if al

null 3 May 11, 2022
[prototype] Generate TypeScript interfaces from Kotlin classes

Kotlinx Serialization TypeScript Generator Kotlinx Serialization TypeScript Generator creates TypeScript interfaces from Kotlinx Serialization classes

null 17 Dec 18, 2022
Event bus for Android and Java that simplifies communication between Activities, Fragments, Threads, Services, etc. Less code, better quality.

EventBus EventBus is a publish/subscribe event bus for Android and Java. EventBus... simplifies the communication between components decouples event s

Markus Junginger 24.2k Jan 7, 2023
A solution to fix obfuscated Java services after ProGuard has run

ProGuard Service Mapper This is a service mapper for the ProGuard Java bytecode

Marvin 1 Jan 10, 2022
PortalController - A rudimentary TeamViewer-like remote control app for Android, using ws.

PortalController A TeamViewer-like app for Android-to-Android remote control, using node.js and websockets (ws). Some insight The reason I call it rud

Mike Anderson 10 Dec 15, 2022
📞 Remote call sample android app using RemoteMonster

?? Remote call sample android app using RemoteMonster

Robin 1 Mar 17, 2022