Guides Android Documentation Document current as of 06/28/2018 12:37 PM. Installation Introduction Each SDL Android library release is published to JCenter. By adding a few lines in their app's gradle script, developers can compile with the latest SDL Android release. To gain access to the JCenter repository, make sure your app's build.gradle file includes the following: repositories { jcenter() } Gradle Build To compile with the a release of SDL Android, include the following line in your app's build.gradle file, dependencies { implementation 'com.smartdevicelink:sdl_android:{version}' } and replace {version} with the desired release version in format of x.x.x . The list of releases can be found here. Examples To compile release 4.6.0, use the following line: dependencies { implementation 'com.smartdevicelink:sdl_android:4.6.0' } To compile the latest minor release of major version 4, use: dependencies { implementation 'com.smartdevicelink:sdl_android:4.+' } Integration Basics Getting Started on Android In this guide, we exclusively use Android Studio. We are going to set-up a bare- bones application so you get started using SDL. NOTE The SDL Mobile library for supports Android 2.2.x (API Level 8) or higher. Required System Permissions In the AndroidManifest for our sample project we need to ensure we have the following system permissions: • Internet - Used by the mobile library to communicate with a SDL Server • Bluetooth - Primary transport for SDL communication between the device and the vehicle's head-unit • Access Network State - Required to check if WiFi is enabled on the device <manifest xmlns:android="http://schemas.android.com/apk/res/ android" package="com.company.mySdlApplication"> ... <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.BLUETOOTH"/ > <uses-permission android:name= "android.permission.ACCESS_NETWORK_STATE" /> ... </manifest> SmartDeviceLink Service A SmartDeviceLink Android Service should be created to manage the lifecycle of an SDL Proxy. The SDL Service enables auto-start by creating the SDL Proxy, which then waits for a connection from SDL. This file also sends and receives messages to and from SDL after connected. Create a new service and name it appropriately, for this guide we are going to call it SdlService . This service must implement the IProxyListenerALM interface: public class SdlService extends Service implements IProxyListenerALM { // Inherited methods from IProxyListenerALM } The IProxyListenerALM interface has most of the callbacks you will receive during the SDL proxy's lifecycle. This includes callbacks for RPC responses. If you created the service using the Android Studio template then the service should have been added to your AndroidManifest.xml otherwise the service needs to be defined in the manifest: <manifest xmlns:android="http://schemas.android.com/apk/res/ android" package="com.company.mySdlApplication"> <application> ... <service android:name=".SdlService" android:enabled="true"/> </application> ... </manifest> Entering the Foreground Because of Android Oreo's requirements, it is mandatory that services enter the foreground for long running tasks. The first bit of integration is ensuring that happens in the onCreate method of the SdlService or similar. Within the service that implements the SDL lifecycle you will need to add a call to start the service in the foreground. This will include creating a notification to sit in the status bar tray. This information and icons should be relevant for what the service is doing/going to do. If you already start your service in the foreground, you can ignore this section. public void onCreate() { super.onCreate(); ... if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.createNotificationChannel(...); Notification serviceNotification = new Notification.Builder(this, * Notification Channel*) .setContentTitle(...) .setSmallIcon(....) .setLargeIcon(...) .setContentText(...) .setChannelId(channel.getId()) .build(); startForeground(id, serviceNotification); } } NOTE The sample code checks if the OS is of Android Oreo or newer to start a foreground service. It is up to the app developer if they wish to start the notification in previous versions. Exiting the Foreground It's important that you don't leave you notification in the notification tray as it is very confusing to users. So in the onDestroy method in your service, simply call the stopForeground method. @Override public void onDestroy(){ //... if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){ NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); if(notificationManager!=null){ //If this is the only notification on your channel notificationManager.deleteNotificationChannel(* Notification Channel*); } stopForeground(true); } } Implementing SDL Proxy Lifecycle In order to correctly use a proxy developers need to implement methods for the proper creation and disposing of an SDL Proxy in our SDLService. NOTE An instance of SdlProxy cannot be reused after it is closed and properly disposed of. Instead, a new instance must be created. Only one instance of SdlProxy should be in use at any given time. public class SdlService extends Service implements IProxyListenerALM { //The proxy handles communication between the application and SDL private SdlProxyALM proxy = null; //... @Override public int onStartCommand(Intent intent, int flags, int startId) { boolean forceConnect = intent !=null && intent.getBooleanExtra( TransportConstants.FORCE_TRANSPORT_CONNECTED, false); if (proxy == null) { try { //Create a new proxy using Bluetooth transport //The listener, app name, //whether or not it is a media app and the applicationId are supplied. proxy = new SdlProxyALM(this.getBaseContext(),this, "Hello SDL App", true, "8675309"); } catch (SdlException e) { //There was an error creating the proxy if (proxy == null) { //Stop the SdlService stopSelf(); } } }else if(forceConnect){ proxy.forceOnConnected(); } //use START_STICKY because we want the SDLService to be explicitly started and stopped as needed. return START_STICKY; } @Override public void onDestroy() { //Dispose of the proxy if (proxy != null) { try { proxy.dispose(); } catch (SdlException e) { e.printStackTrace(); } finally { proxy = null; } } super.onDestroy(); } @Override public void onProxyClosed(String info, Exception e, SdlDisconnectedReason reason) { //Stop the service stopSelf(); } //... } onProxyClosed() is called whenever the proxy detects some disconnect in the connection, whether initiated by the app, by SDL, or by the device’s bluetooth connection. As long as the exception does not equal Sdl_PROXY_CYCLED or BLUETOOTH_DISABLED, the proxy would be reset for the exception SDL_PROXY_DISPOSED. NOTE We must properly dispose of our proxy in the onDestroy() method because SDL will issue an error that it lost connection with the app if the connection fails before calling proxy.dispose() . Implementing IProxyListenerALM Methods ONONHMISTATUS() In our SdlService , the onOnHMIStatus() method is where you should control your application with SDL various HMI Statuses. When you receive the first HMI_FULL, you should initialize your app on SDL by subscribing to buttons, registering addcommands, sending an initial show or speak command, etc. @Override public void onOnHMIStatus(OnHMIStatus notification) { switch(notification.getHmiLevel()) { case HMI_FULL: //send welcome message, addcommands, subscribe to buttons ect break; case HMI_LIMITED: break; case HMI_BACKGROUND: break; case HMI_NONE: break; default: return; } } SmartDeviceLink Router Service The SdlRouterService will listen for a bluetooth connection with an SDL enabled module. When a connection happens, it will alert all SDL enabled apps that a connection has been established and they should start their SDL services. We must implement a local copy of the SdlRouterService into our project. The class doesn't need any modification, it's just important that we include it. We will extend the com.smartdevicelink.transport.SdlRouterService in our class named SdlRouterService :
Description: