It is a library that provides a common interface for mobile services for Android developers. Its aim is removing special mobile service dependencies for your app code.
This has mainly two benefits:
1- It removes creation and lifecycle control code from your app code. So your classes get rid of one extra responsibility.(Separation of Concerns)
2- Makes it possible to use different mobile services. For example not all Android devices has Google Mobile Services(GMS). By doing this library you can use
different services without modifying your app code.
This library contains 2 services for now: Google Mobile Services(GMS) and Huawei Mobile Services(HMS). This library will grow with the added services. If you want to contribute don't hesitate to create PR's :)
Currently added services: MapKit
, Location
, Analytics
, CreditCardScanner
, Awareness
, Scan
, Translate
, Speech To Text
, Text To Speech
, Object Detection
, Text Recognition
, Face Detection
, Language Detection
, Image Classification
, Account
, Auth
, Safety
, Crash
, Push
, Site
, Ads
, Identity
and Remote Config
.
buildscript {
ext {
toolsBuildGradleVersion = '7.1.1'
}
dependencies {
classpath "com.android.tools.build:gradle:$toolsBuildGradleVersion"
classpath 'com.huawei.agconnect:agcp:1.9.1.301'
classpath "io.realm:realm-gradle-plugin:10.13.3-transformer-api"
classpath 'com.google.gms:google-services:4.3.15'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.5'
}
}
plugins {
id 'com.android.application' version '8.0.2' apply false
id 'com.android.library' version '8.0.2' apply false
id 'org.jetbrains.kotlin.android' version '1.8.20' apply false
id 'com.google.gms.google-services' version '4.4.0' apply false
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Step 2. Get the agconnect-services.json file from the AGC Console and google-services.json file from Firebase Console. Then, place it under the app module. And, add plugins to app level gradle file header.
apply plugin: 'com.huawei.agconnect'
apply plugin: 'com.google.gms.google-services'
dependencies {
implementation(platform("com.google.firebase:firebase-bom:32.5.0"))
implementation 'com.huawei.agconnect:agconnect-core:1.9.1.300'
implementation 'com.huawei.hms:hmscoreinstaller:6.11.0.301'
}
pluginManagement {
repositories {
maven { url 'https://developer.huawei.com/repo/' }
}
}
dependencyResolutionManagement {
repositories {
maven { url 'https://developer.huawei.com/repo/' }
maven { url "https://jitpack.io" }
}
}
Step 5. Add the this configuration setting that disables the instrumentation of the application performance management system:
apmsInstrumentationEnabled=false
com.github.Explore-In-HMS.common-mobile-services
latest version: 3.0.3
implementation 'com.github.Explore-In-HMS.common-mobile-services:mapkit:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:location:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:analytics:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:creditcardscanner:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:awareness:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:scan:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:translate:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:speechtotext:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:texttospeech:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:objectdetection:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:textrecognition:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:ads:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:facedetection:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:languagedetection:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:imageclassification:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:account:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:auth:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:safety:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:crash:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:push:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:site:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:identity:<versionName>'
implementation 'com.github.Explore-In-HMS.common-mobile-services:remoteconfig:<versionName>'
Libraries usually return data in a common data wrapper class: ResultData
. It has three states: Success
, Failed
and Loading
. This wrapper class helps us to manage the data status.
sealed class ResultData<out T>{
data class Loading(val nothing: Nothing? = null): ResultData<Nothing>()
data class Success<out T>(val data: T? = null): ResultData<T>()
data class Failed(val error: String? = null,val errorModel: ErrorModel?=null): ResultData<Nothing>()
}
This library wraps a mapview to use it in application code. It has CommonMap interface which can be GoogleCommonMapImpl or HMSCommonMapImpl. A custom view created to hold these map views: CommonMapView. This view also manages lifecycle events of its map.
First add Google Map api key to Manifest.xml.
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="xxx-xxx"/>
Add CommonMapView to your layout file
<com.hms.commonmobileservices.mapkit.CommonMapView
android:id="@+id/mapView"
app:hms_api_key="..."
android:layout_width="match_parent"
android:layout_height="match_parent" />
It's advised to put the api_key that taken from AppGallery console
Then in your Activity or Fragment
val commonMap=mapView.onCreate(savedInstanceState,lifecycle).apply {
getMapAsync {
it.addMarker("Marker", "Snippet", 41.0540255, 29.0129607)
it.animateCamera(41.0540255, 29.0129607, 10f)
}
}
CommonMapView.onCreate()
function needs savedInstanceState and lifecycle. It uses savedInstanceState
to keep the map state when Activity
/Fragment
is destroyed and recreated. Uses lifecycle
to redirect lifecycle events to the map view via LifecycleObserver
. So you don't need to override lifecycle callback like onDestroy()
and call commonMap.onDestroy()
getMapAsync()
function takes a callback that informs you when the map is ready. After this callback is called you can use commonMap
functions.
Here is all functions of CommonMap
interface CommonMap : UISettings{
fun getMapView(): View
fun onCreate(bundle: Bundle?)
fun getMapAsync(onMapReadyListener: (map: CommonMap) -> Unit)
fun addMarker(title: String?=null,
snippet: String?=null,
latitude: Double,
longitude: Double,
iconBitmap: Bitmap?=null,
anchor : Pair<Float,Float>?=null
) : CommonMarker
fun addPolygon(commonPolygonOptions: CommonPolygonOptions) : CommonPolygon
fun setOnInfoWindowClickListener(markerClickCallback : (markerTitle: String?,
markerSnippet: String?) -> Unit)
fun setOnMapClickListener(onClick : (commonLatLng: CommonLatLng) -> Unit)
fun moveCamera(latitude: Double, longitude: Double, zoomRatio: Float)
fun animateCamera(latitude: Double, longitude: Double, zoomRatio: Float)
fun setMyLocationEnabled(myLocationEnabled: Boolean?,context: Context) : Boolean
fun clear()
fun onSaveInstanceState(bundle: Bundle)
fun onStart()
fun onResume()
fun onPause()
fun onStop()
fun onDestroy()
fun onLowMemory()
}
You can also use UISettings
functions
interface UISettings {
fun isCompassEnabled(): Boolean
fun setCompassEnabled(compassEnabled: Boolean?)
fun isIndoorLevelPickerEnabled(): Boolean
fun setIndoorLevelPickerEnabled(indoorLevelPickerEnabled: Boolean?)
fun isMapToolbarEnabled(): Boolean
fun setMapToolbarEnabled(mapToolbarEnabled: Boolean?)
fun isMyLocationButtonEnabled(): Boolean
fun setMyLocationButtonEnabled(myLocationButtonEnabled: Boolean?)
fun isRotateGesturesEnabled(): Boolean
fun setRotateGesturesEnabled(rotateGesturesEnabled: Boolean?)
fun isScrollGesturesEnabled(): Boolean
fun setScrollGesturesEnabled(scrollGesturesEnabled: Boolean?)
fun isScrollGesturesEnabledDuringRotateOrZoom(): Boolean
fun setScrollGesturesEnabledDuringRotateOrZoom(scrollGesturesEnabledDuringRotateOrZoom: Boolean?)
fun isTiltGesturesEnabled(): Boolean
fun setTiltGesturesEnabled(tiltGesturesEnabled: Boolean?)
fun isZoomControlsEnabled(): Boolean
fun setZoomControlsEnabled(zoomControlsEnabled: Boolean?)
fun isZoomGesturesEnabled(): Boolean
fun setZoomGesturesEnabled(zoomGesturesEnabled: Boolean?)
fun setAllGesturesEnabled(allGestureEnable: Boolean?)
}
This library provides a CommonLocationClient. It is a base class for GMS FusedLocationProviderClient
and HMS FusedLocationProviderClient
. This library handles enabling GPS and getting location permissions at runtime.
First, initialize CommonLocationClient
:
val locationClient: CommonLocationClient? = LocationFactory.getLocationClient(this,lifecycle)
It needs Activity
to handle runtime permissions, create fused client and check GPS setting is on or off. Needs lifecycle
to manage the lifecycle of its element according to Activity
/Fragment
lifecycles. Finally needs to permission callbacks implemented by the application code. It covers denying permissions one time and permanently cases.
Then you must check if the GPS setting is on or off. If it is enabled you are ready to use CommonLocationClient
.
locationClient.enableGps{enableGPSFinalResult, error ->
when(enableGPSFinalResult){
EnableGPSFinalResult.ENABLED -> showToast("GPS Enabled")
EnableGPSFinalResult.FAILED -> showToast("GPS Enabling Failed")
EnableGPSFinalResult.USER_CANCELLED -> showToast("GPS Enabling Cancelled")
}
}
If enableGPSFinalResult
is EnableGPSFinalResult.ENABLED
you can use clients functions.
Getting last known location:
locationClient?.getLastKnownLocation{
when(it.state){
LocationResultState.SUCCESS->{
Toast.makeText(
context,
"Current Location Latitude: ${it.location?.latitude} ,Current Location Longitude: ${it.location?.longitude}",
Toast.LENGTH_LONG
).show()
}
LocationResultState.FAIL->{
Toast.makeText(
context,
"Failed to get current location",
Toast.LENGTH_LONG
).show()
}
}
}
Getting location continuously:
locationClient?.requestLocationUpdates(priority = Priority.PRIORITY_HIGH_ACCURACY,interval = 1000){
var message:String?=null
when(it.state){
LocationResultState.SUCCESS->{
message="Current Latitude: ${it.location?.latitude} \nCurrent Longitude: ${it.location?.longitude}"
}
LocationResultState.FAIL->{
message="Failed to get current location"
}
LocationResultState.GPS_DISABLED->{
message="User disabled gps"
}
LocationResultState.LOCATION_UNAVAILABLE->{
message="Location unavailable due to the environment"
}
}
Log.d(TAG,message)
locationUpdatesLiveData.value=message
}
When you don't need to location updates you can remove listener like this:
locationClient?.removeLocationUpdates()
To use the mock location function, go to Settings > System & updates > Developer options > Select mock location app and select the desired app. (If Developer options is unavailable, go to Settings > About phone and tap Build number for seven consecutive times. Then, Developer options will be displayed on System & updates.) You need to add necessary permission to use Mock location feature to AndroidManifest.xml file.
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
fun setMockMode(isMockMode : Boolean) : Work<Unit>
commonLocationClient?.setMockMode(true).addOnSuccessListener { }.addOnFailureListener { }
fun setMockLocation(location: Location): Work<Unit>
val mockLocation = Location(LocationManager.GPS_PROVIDER)
mockLocation.latitude = latitude
mockLocation.longitude = longitude
commonLocationClient?.setMockLocation(mockLocation).addOnSuccessListener { }.addOnFailureListener { }
The usage of the Geofence feature is as follows. To use the geofence service APIs of Location Kit, declare the ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions in the AndroidManifest.xml file.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
First you have to initialize the CommonGeofenceService object.
private var geofenceService: CommonGeofenceService? = null
private var geofenceList: ArrayList<Geofence>? = null
private var pendingIntent: PendingIntent?=null
geofenceService = CommonGeofenceService()
pendingIntent = getPendingIntent()
geofenceList = ArrayList()
geofenceList!!.add(Geofence()
.also { it.uniqueId= "testGeofence" }.also { it.conversions = Geofence.ENTER_GEOFENCE_CONVERSION }
.also { it.validDuration = Geofence.GEOFENCE_NEVER_EXPIRE }.also { it.latitude = latitude }.also { it.longitude = longitude }
.also { it.radius = 20F })
fun createGeofenceRequest(): GeofenceRequestRes{
return GeofenceRequestRes().also { it.geofenceList = geofenceList }.also { it.initConversion = GeofenceRequestRes.INITIAL_TRIGGER_ENTER }
}
You should initialize the pendingIntent object that we have created.
private fun getPendingIntent(): PendingIntent? {
val intent = Intent(this, GeofenceBroadcastReceiver::class.java)
intent.action = "com.hms.commonmobileservices.GEOFENCE"
return PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
}
After all this process, we need to send the request to add a geofence via createGeofenceList()
method.
fun createGeofenceList(context: Context, geofenceReq: GeofenceRequestRes,pendingIntent: PendingIntent): Work<Unit>
geofenceService.createGeofenceList(applicationContext,createGeofenceRequest(),pendingIntent)
.addOnSuccessListener {
}.addOnFailureListener {
}
After adding Geofence, we need to create a Broadcast receiver and define it in AndroidManifest file so that Geofence can be triggered.
<receiver android:name=".GeofenceBroadcastReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.hms.commonmobileservices.GEOFENCE" />
</intent-filter>
</receiver>
We will be able to listen to the Geofence triggering process thanks to the Brodcast receiver.Thanks to our CommonGeofenceData class, you can get all information about the triggered event.
class GeofenceBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
val geofenceData = CommonGeofenceData().fetchDataFromIntent(context,intent)
val errorCode = geofenceData.errorCode
val conversion = geofenceData.conversion
val convertingGeofenceList = geofenceData.convertingGeofenceList
val convertingLocation = geofenceData.convertingLocation
val isFailure = geofenceData.isFailure
}
}
With the deleteGeofenceList()
method, you can delete the previously created geofence list according to the geofence id list or according to the pending intent value.
fun deleteGeofenceList(context: Context,geofenceList:List<String>):Work<Unit>
fun deleteGeofenceList(context: Context,pendingIntent: PendingIntent):Work<Unit>
val geofenceIdList : ArrayList<String> = ArrayList()
geofenceIdList.add("testGeofence")
geofenceService.deleteGeofenceList(applicationContext,geofenceIdList)
.addOnSuccessListener { }
.addOnFailureListener { }
geofenceService.deleteGeofenceList(applicationContext,pendingIntent)
.addOnSuccessListener { }
.addOnFailureListener { }
Thanks to the Activity Recognition feature, you can follow the user's activity instantly. To use the activity recognition service in versions earlier than Android 10, add the following permission in the AndroidManifest.xml file.
<uses-permission android:name="com.huawei.hms.permission.ACTIVITY_RECOGNITION"/>
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION"/>
To use the activity recognition service in Android 10 and later versions, add the following permission in the AndroidManifest.xml file;
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
After adding the required permissions, you must create and initialize the CommonActivityIdentificationService
object.
private var activityIdentificationService : CommonActivityIdentificationService?=null
private var pendingIntent: PendingIntent? = null
activityIdentificationService = CommonActivityIdentificationService()
pendingIntentEdit = getPendingIntent()
private fun getPendingIntent(): PendingIntent?{
val intent = Intent(this, ActivityRecognitionReceiver::class.java)
intent.action = "com.hms.commonmobileservices.ACTIVITY_RECOGNITION"
return PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
}
With the createActivityIdentificationUpdates()
method, the user's activities are controlled according to the specified time.
fun createActivityIdentificationUpdates(context: Context,intervalMillis:Long, pendingIntent: PendingIntent):Work<Unit>
activityIdentificationService.createActivityIdentificationUpdates(applicationContext,5000,pendingIntent)
.addOnSuccessListener { }
.addOnFailureListener { }
You can follow to the user activities with the Broadcast Receiver we will create.
<receiver android:name=".ActivityRecognitionReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.hms.commonmobileservices.ACTIVITY_RECOGNITION" />
</intent-filter>
</receiver>
With fetchDataFromIntent()
method you can get detected activities status list.
fun fetchDataFromIntent(context:Context, intent:Intent): CommonActivityIdentificationResponse
class ActivityRecognitionReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
val activityIdentificationResponse = CommonActivityIdentificationResponse().fetchDataFromIntent(context,intent)
val detectedActivityList = activityIdentificationResponse.activityIdentificationDataList
}
}
To Stop requesting activity identification updates, you can use deleteActivityIdentificationUpdates()
method.
fun deleteActivityIdentificationUpdates(context: Context,pendingIntent: PendingIntent):Work<Unit>
activityIdentificationService.deleteActivityIdentificationUpdates(applicationContext,pendingIntent)
.addOnSuccessListener { }
.addOnFailureListener { }
Activity transition is a process of detecting user activity converting from one to another. You can call the createActivityConversionUpdates()
method in your app to request user activity conversion updates.
fun createActivityConversionUpdates(context: Context,activityConversionReq: CommonActivityConversionReq,pendingIntent: PendingIntent):Work<Unit>
val activityConversionEnter = CommonActivityConversionInfo()
.also { it.activityType = CommonActivityIdentificationData().activityType(applicationContext,CommonActivityIdentificationData.STILL)}
.also { it.conversionType = CommonActivityConversionInfo.ENTER_ACTIVITY_CONVERSION }
val activityConversionExit = CommonActivityConversionInfo()
.also { it.activityType = CommonActivityIdentificationData().activityType(applicationContext,CommonActivityIdentificationData.STILL) }
.also { it.conversionType = CommonActivityConversionInfo.EXIT_ACTIVITY_CONVERSION }
val activityConversionList: MutableList<CommonActivityConversionInfo> = ArrayList()
activityConversionList.add(activityConversionEnter)
activityConversionList.add(activityConversionExit)
val activityConRequest = CommonActivityConversionReq()
activityConRequest.activityConversions = activityConversionList
activityIdentificationService.createActivityConversionUpdates(applicationContext,activityConRequest,pendingIntent)
.addOnSuccessListener { }
.addOnFailureListener { }
You can receive the broadcast activity transition result with broadcast receiver. With Common fetchDataFromIntent()
method you can get activity transition status.
fun fetchDataFromIntent(context: Context, intent: Intent): CommonActivityConversionResponse
class ActivityRecognitionReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
val activityTransitionResponse = CommonActivityConversionResponse().fetchDataFromIntent(context,intent)
val activityTransitionList = activityTransitionResponse.getActivityConversionDataList
}
}
If you want to stop getting activity transition information, you can use deleteActivityConversionUpdates()
method.
fun deleteActivityConversionUpdates(context: Context,pendingIntent: PendingIntent):Work<Unit>
activityIdentificationService.deleteActivityConversionUpdates(applicationContext,pendingIntent)
.addOnSuccessListener { }
.addOnFailureListener { }
It is made to ease logging for your project. You can log your event with a one line of code.
First, get the instance of common logger by calling CommonAnalytics.instance(this)
. The function takes a context instance as a parameter. Then returns an implementation of CommonAnalytics
. It can be the class that uses Firebase
or HiAnalyticsTools
for logging.
If you want to implement your own logger you can just implement the CommonAnalytics interface and use it instead.
You can log your events with classic Bundle.
val myEvent = Bundle().apply {
putString("productName", "socks")
putInt("quantity", 5)
}
CommonAnalytics.instance(this)?.saveEvent("cartEvent", myEvent)
You can also delete previously collected data with the "clearCachedData()" method. Data configured through the following APIs will be cleared:
onEvent
setUserId
setUserProfile
addDefaultEventParams
CommonAnalytics.instance(this)?.clearCachedData()
You can set whether to enable event tracking. If event tracking is disabled, no data is recorded or analyzed. The default value is true
CommonAnalytics.instance(this)?.setAnalyticsEnabled(false)
User id can be assigned. When this method is called, a new session will be generated if the old value of id is not empty and is different from the new value. If you do not want to use id to identify a user (for example, when a user signs out), you must set id to null.
CommonAnalytics.instance(this)?.setUserId("id")
You can set user attributes. The values of user attributes remain unchanged throughout the app lifecycle and during each session. A maximum of 25 user attributes are supported. If the name of an attribute set later is the same as that of an existing attribute, the value of the existing attribute is updated.
CommonAnalytics.instance(this)?.setUserProfile("name", "value")
This method sets the session timeout interval. A new session will be generated when an app is running in the foreground but the interval between two adjacent events exceeds the specified timeout interval. The minimum value is 5 seconds, and the maximum value is 5 hours. If the specified value is beyond the value range, the boundary value is used. By default, the timeout interval is 1,800,000 milliseconds (that is, 30 minutes).
val milliseconds = 10000
CommonAnalytics.instance(this)?.setSessionDuration(milliseconds)
You can also add default event parameters. These parameters will be added to all events except the automatically collected events. If the name of a default event parameter is the same as that of an event parameter, the event parameter will be used.
val params = Bundle().apply {
putString("productName", "keyboard")
putInt("quantity", 3)
}
CommonAnalytics.instance(this)?.addDefaultEventParams(params)
If you want to obtain AAID then you can use getAAID()
method. This method returns to you AAID as a string.
CommonAnalytics.instance(this)?.getAAID()
This library reads a credit card with device camera. It uses Huawei ML-Card-Bcr library to scan image. But it is inherited from CreditCardScanner
common interface, so you can use your own implementation of credit card reader. HMS library does not require a Huawei device or HMS Core, so this library works well in all devices.
Get CreditCardScanner
instance and call scan()
function like this:
CreditCardScanner.instance(this)?.scan {
when(it){
is ResultData.Success ->{
// handle success data
}
is ResultData.Failed->{
// show error to user
}
is ResultData.Loading->{
// show loading indicator
}
}
The scan()
function takes a callback lambda function as a parameter. The lambda function gives us a ResultData
sealed class object.
fun scan(callback: (ResultData<CommonCreditCardResult>) -> Unit)
This library has a ScanError
class which is inherited from ErrorModel
of ResultData
. ScanError
as error states to manage scan error situations.
data class ScanError(
val errorString: String,
val scanErrorType: ScanErrorType = ScanErrorType.ERROR
) : ErrorModel(errorString) {
enum class ScanErrorType {
USER_CANCELED, ERROR, DENIED
}
}
Awareness SDK provides your app with the ability to obtain contextual information including users' behavior, audio device status, weather, and current time. Depending on the situation, this information can be obtained in certain instantly.
To use Google Awareness Api Key, you need to get Google Awareness Api Key. With this Api Key, add the code block to your Manifest.xml file as follows.
<meta-data
android:name="com.google.android.awareness.API_KEY"
android:value="GOOGLE_AWARENESS_API_KEY"/>
By using the code block below, you instantly get the data from the class you want to use the Awareness SDK for.
HuaweiGoogleAwarenessManager(this).getWeather {dataArray ->
dataArray.handleSuccess {
it.data?.forEach {value ->
Log.d("AWARENESS_WEATHER",WeatherDataValue.valueOf(value)!!.name)
}
}
}
The getWeather()
or getBehavior()
or getHeadset()
or getTime()
functions take a callback lambda function as a parameter. The lambda function gives us a ResultData
sealed class object.
fun getWeather(callback: (weatherVal: ResultData<IntArray>) -> Unit)
Scan SDK scans and parses all major 1D and 2D barcodes, helping you quickly barcode scanning functions into your apps.
The scan process is started with the following line of code. scanBarcodeResultCode is the variable that is the result of OnActivityResult.
HuaweiGoogleScanManager(this).performScan(this,scanBarcodeResultCode)
After scanning is done, The result of the scanning process gets from onActivityResult. Using the parseScanToTextData function, the data is converted to string format.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (data != null) {
if (requestCode == scanBarcodeResultCode) {
HuaweiGoogleScanManager(this).parseScanToTextData({resultData->
Toast.makeText(this,"The result is -> ${resultData.handleSuccess {
it.data
}}",Toast.LENGTH_SHORT).show()
},this,data)
}
}
}
The parseScanToTextData()
function takes a callback lambda function as a parameter. The lambda function gives us a ResultData
sealed class object.
fun parseScanToTextData(callback: (scanToTextResult: ResultData<String>) -> Unit, activity: Activity, data:Intent)
With the support of an on-device model, the on-device translation service can translate text from the source language into the target language.
First, get the instance of language detection by calling Translator.getClient(context)
The function takes context
as parameter.
val translator = Translator.getClient(this)
To translate a string of text, pass the text, source language and target language to translate(...)
method
translator.translate("text","source-lang","target-lang"){ translateResult ->
when(translateResult){
is TranslateResult.Success -> {
Log.d("Translate result: ", translateResult.translatedText)
}
is TranslateResult.Error -> {
//Handle exception -> translateResult.exception
}
}
}
Make sure the required translation model has been downloaded to the device.
translator.requiresModelDownload("lang-code"){ requiresModelDownloadResult ->
when(requiresModelDownloadResult){
is RequiresModelDownloadResult.Required -> {
//You have to download the model to be able to translate
}
is RequiresModelDownloadResult.NotRequired -> {
//You can translate text
}
is RequiresModelDownloadResult.Error -> {
//Handle exception -> requiresModelDownloadResult.exception
}
}
}
On-device models can be download.
translator.downloadModel("lang-code"){ downloadModelResult ->
when(downloadModelResult){
is DownloadModelResult.Success -> {
//Model Downloaded
}
is DownloadModelResult.Error -> {
//Handle exception -> downloadModelResult.exception
}
}
}
Delete an unnecessary model package.
translator.deleteModel("lang-code"){ deleteModelResult ->
when(deleteModelResult){
is DeleteModelResult.Success -> {
//Model Deleted
}
is DeleteModelResult.Error -> {
//Handle exception -> deleteModelResult.exception
}
}
}
Ensure that the close()
method is called when the Translator object will no longer be used.
translator.close()
Speech to Text can recognize speech not longer than 60s and convert the input speech into text in real time. This service uses industry-leading deep learning technologies to achieve a recognition accuracy of over 95%. Currently, Mandarin Chinese (including Chinese-English bilingual speech), English, French, German, Spanish, and Italian can be recognized. Click here to view instantly supported speech to text languages and language codes.
The speech to text process is started with the following line of code. speechToTextResultCode is the variable that is the result of OnActivityResult. The language to be spoken in must be chosen.
HuaweiGoogleSpeechToTextManager(this).performSpeechToText(this,speechToTextResultCode,"en-US","API_KEY")
After speaking is done, The result of the speech to text process gets from onActivityResult. Using the parseSpeechToTextData function, the data is converted to string format.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == speechToTextResultCode) {
if (data != null) {
HuaweiGoogleSpeechToTextManager(this).parseSpeechToTextData(
{
it.handleSuccess {
Log.d("Speech to text result: ",it.data.toString())
}
}, this, data, resultCode
)
}
}
}
The parseSpeechToTextData()
function takes a callback lambda function as a parameter. The lambda function gives us a ResultData
sealed class object.
fun parseSpeechToTextData(callback: (speechToTextResult: ResultData<String>) -> Unit, activity:Activity, data:Intent, resultCode:Int)
Text to speech (TTS) can convert text information into audio output in real time. Rich timbres are provided and the volume and speed can be adjusted (5x adjustment is supported for Chinese and English), thereby natural voices can be produced. This service uses the deep neural network (DNN) synthesis mode and can be quickly integrated through the on-device SDK to generate audio data in real time. Click here to view instantly supported text to speech languages and person types.
The text to speech process is started with the following line of code. The languageCode and personType must be chosen.
HuaweiGoogleTextToSpeechManager(this).runTextToSpeech(
"Hello, how are you?",
this,
API_KEY,
"en-US",
"en-US-st-3"
)
The runTextToSpeech()
function takes text, activity, apiKey, languageCode, personType as a parameter. Then the text to speech process will start.
fun runTextToSpeech(text: String, activity: Activity, apiKey: String, languageCode: String, personType: String)
The stopTextToSpeech()
function stops the speech process.
fun stopTextToSpeech()
The object detection and tracking service can detect and track multiple objects in an image, so they can be located and classified in real time. A maximum of eight objects can be detected and tracked concurrently. The following object categories are supported: household products, fashion goods, food, places, plants, faces, and others.
Parameters that should be used to use the object detection feature; callback, context, bitmap, api key. Then the objects which in the picture will be detected.
HuaweiGoogleObjectDetectionManager(this).staticImageDetection({
when(it) {
is ResultData.Success -> {
Log.d("Object detection result: ", it.data)
}
is ResultData.Failed -> {
Log.d("error: ", error occured)
}
}
},this,bitmap!!,apiKey
The staticImageDetection()
function takes a callback lambda function as a parameter. The lambda function gives us a ResultData
sealed class object.
fun staticImageDetection(callback: (detectedValue: ResultData<List<Any>>) -> Unit, activity: Activity, bitmap: Bitmap, apiKey: String)
The text recognition service can extract text from images of receipts, business cards, and documents. This service is useful for industries such as printing, education, and logistics. You can use it to create apps that handle data entry and check tasks.
Parameters that should be used to use the text recognition feature; bitmap and callback. Then the text which in the image will be recognized.
HuaweiGoogleTextRecognitionManager(this).textRecognition(bitmap) { result ->
when (result) {
is RecognitionResult.Success -> {
Log.d("Text Recognition result: ", result.data)
}
is RecognitionResult.Error -> {
Log.d("Text Recognition result: ", result.errorMessage)
}
}
}
The textRecognition()
function takes a callback lambda function as a parameter. The lambda function gives us a RecognitionResult
sealed class object.
fun textRecognition(bitmap: Bitmap, callback: (recognizedValue: RecognitionResult<Any>) -> Unit)
Allows you to show ads in your app.
Firstly, you need add your AdMob app ID
value in AndroidManifest.xml
to use Google AdMob.
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-YOUR-CA_APP_PUB_HERE" />
Banner ads are rectangular images that occupy a spot within an app's layout, either at the top, middle, or bottom of the device screen. Banner ads refresh automatically at regular intervals. When a user clicks a banner ad, the user is redirected to the advertiser's page.
Add CommonBannerAdView
to your layout file.
<com.hms.lib.commonmobileservices.ads.banner.CommonBannerAdView
android:id="@+id/cvBannerAd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hms_ad_unit_id="**your_hms_ad_unit_id**"
app:gms_ad_unit_id="**your_gms_ad_unit_id**"
app:ad_size="large_banner"
app:layout_constraintBottom_toBottomOf="parent"
/>
ad_size | GMS | HMS |
---|---|---|
banner | AdSize.BANNER | BannerAdSize.BANNER_SIZE_320_50 |
large_banner | AdSize.LARGE_BANNER | BannerAdSize.BANNER_SIZE_360_57 |
full_banner | AdSize.FULL_BANNER | BannerAdSize.BANNER_SIZE_360_144 |
leaderboard | AdSize.LEADERBOARD | BannerAdSize.BANNER_SIZE_468_60 |
medium_rectangle | AdSize.MEDIUM_RECTANGLE | BannerAdSize.BANNER_SIZE_320_100 |
smart_banner | AdSize.SMART_BANNER | BannerAdSize.BANNER_SIZE_DYNAMIC |
wide_skyscraper | AdSize.WIDE_SKYSCRAPER | BannerAdSize.BANNER_SIZE_320_50 |
Then in your Activity or Fragment, you need to call initialize()
function to get banner ad. By passing BannerAdLoadCallback
you will get IBannerAd
instance in order to show ad.
val commonAdView : CommonBannerAdView = findViewById(R.id.cvBannerAd)
commonAdView.initialize(
object : BannerAdLoadCallback {
override fun onAdLoadFailed(adError: String) {
Log.e("ERROR AD: ", adError)
}
override fun onBannerAdLoaded(bannerAd: IBannerAd) {
Log.i("SUCCESS! ", bannerAd.toString())
}
}
)
Interstitial ads are full-screen ads that cover the interface of an app. Such an ad is displayed when a user starts, pauses, or exits an app, without disrupting the user's experience.
Call the InterstitialAd.load()
function to load an interstitial ad by passing the context
, Google Mobile Services (GMS) ad unit ID, Huawei Mobile Services (HMS) ad unit ID, and an instance of InterstitialAdLoadCallback
to handle the ad loading process. If the ad fails to load, the onAdLoadFailed(adError: String)
method logs the error message; if the ad successfully loads, the onInterstitialAdLoaded(interstitialAd: IInterstitialAd)
method displays the ad by calling interstitialAd.show(requireActivity())
.
InterstitialAd.load(
context = requireContext(),
gmsAdUnitId = "**your_gms_ad_unit_id**",
hmsAdUnitId = "**your_hms_ad_unit_id**",
callback = object : InterstitialAdLoadCallback {
override fun onAdLoadFailed(adError: String) {
Log.e("ERROR AD: ", adError)
}
override fun onInterstitialAdLoaded(interstitialAd: IInterstitialAd) {
Log.i("SUCCESS! ", interstitialAd.toString())
interstitialAd.show(requireActivity())
}
}
)
Rewarded Ads are shown to users in exchange for a reward, such as an extra life or in-app currency. You can specify the reward values associated with the ad units in your app and set different rewards for different ad units. Users will receive the reward for interacting with the ad without needing to install anything.
Create an IRewardedAd
variable in order to get instance when ads showing is ready.
private lateinit var rewardedAd: IRewardedAd
First, you need to call static RewardedAd.load()
function to get rewarded ad instance.
By passing context
, hmsAdUnitId
, gmsAdUnitId
and RewardedAdLoadCallback
you will get IRewardedAd
instance in order to show ad.
RewardedAd.load(
this,
"**your_hms_ad_unit_id**",
"**your_gms_ad_unit_id**",
object : RewardedAdLoadCallback {
override fun onAdLoadFailed(adError: String) {
Log.e("ERROR AD:", adError)
}
override fun onRewardedAdLoaded(rewardedAd: IRewardedAd) {
Log.i("SUCCESS!", rewardedAd.toString())
rewardedAd = rewardedAd
}
}
)
Call show()
function whenever you want to show ad.
You need to pass context
and UserRewardEarnedListener
params in order to get reward after user watched the ad.
You can get reward value by calling getAmount()
function.
rewardedAd.show(
this,
object : UserRewardEarnedListener {
override fun onUserEarnedReward(item: IRewardItem) {
Log.d("onUserEarnedReward", "${item.getAmount()} ${item.getTypeOrName()}")
}
}
)
Splash ads are displayed immediately after an app is launched, even before the home screen of the app is displayed. You need to design a default slogan image for the app in advance and ensure that the default slogan image is displayed before a splash ad is loaded, enhancing user experience.
Add CommonSplashAdView
to your XML layout file.
app:gms_splash_ad_unit_id
and app:hms_splash_ad_unit_id
are used to set the ad unit IDs for Google Mobile Services and Huawei Mobile Services respectively; replace these with your actual ad unit IDs.
<com.hms.lib.commonmobileservices.ads.splash.CommonSplashAdView
android:id="@+id/commonSplashView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:gms_splash_ad_unit_id="**your_gms_ad_unit_id**"
app:hms_splash_ad_unit_id="**your_hms_ad_unit_id**" />
Find the CommonSplashAdView
in your layout.
val splashAdView: CommonSplashAdView = findViewById(R.id.commonSplashView)
Call the load()
function on the CommonSplashAdView
instance to load the splash ad, passing an instance of SplashAdLoadCallback
to handle the ad loading process. If the ad fails to load, the onAdLoadFailed(adError: String)
method logs the error message; if the ad successfully loads, the onSplashAdLoaded(splashAd: ISplashAd)
method displays the ad by calling splashAd.show(requireActivity())
.
splashAdView.load(object : SplashAdLoadCallback {
override fun onAdLoadFailed(adError: String) {
Log.e("ERROR SPLASH AD: ", adError)
}
override fun onSplashAdLoaded(splashAd: ISplashAd) {
Log.i("SUCCESS!", splashAd.toString())
splashAd.show(requireActivity())
}
})
With ML Kit's face detection API, you can detect faces in an image, identify key facial features, and get the contours of detected faces. Note that the API detects faces, it does not recognize people. With face detection, you can get the information you need to perform tasks like embellishing selfies and portraits, or generating avatars from a user's photo. Because ML Kit can perform face detection in real time, you can use it in applications like video chat or games that respond to the player's expressions.
Parameters that should be used to use the object detection feature; callback, context, bitmap, api key. Then the objects which in the picture will be detected.
HuaweiGoogleFaceDetectionManager(this).faceDetection({
when (it) {
is ResultData.Success -> {
Log.d("Object detection result: ", it.data)
}
is ResultData.Failed -> {
Log.d("Object detection result: ", it.data)
}
}
}, this, bitmap!!, apiKey)
The faceDetection()
function takes a callback lambda function as a parameter. The lambda function gives us a ResultData
sealed class object.
fun faceDetection(callback: (detectedValue: ResultData<List<Any>>) -> Unit, activity: Activity, bitmap: Bitmap, apiKey: String)
The language detection service can detect the language of text. ML Kit detects languages in text and returns the language codes (the ISO 639-1 standard is used for languages, other than certain languages specified) and their respective confidences or the language code with the highest confidence.
You can configure your app to automatically download the model to the device after your app is installed from the Play Store or AppGallery. Add the following statements to the AndroidManifest.xml file.
<manifest
...
<meta-data
android:name="com.huawei.hms.ml.DEPENDENCY"
android:value= "langdetect"/>
<meta-data
android:name="com.google.mlkit.vision.DEPENDENCIES"
android:value="langid" >
...
</manifest>
First, get the instance of language detection by calling HuaweiGoogleLanguageDetector.getClient(....)
The function takes context
and confidence threshold
as parameters. The confidence threshold
can be null. If you give a confidence threshold, ML Kit will use the minimum confidence threshold for language detection, otherwise it will use the default ML Kit settings.
val languageDetector = HuaweiGoogleLanguageDetector.getClient(context, confidenceThreshold?)
To detect the language of a string, pass the string to the detectLanguage() method.
languageDetector.detectLanguage("sourceText"){ detectResult ->
when(detectResult){
is DetectionResult.Success -> {
Log.d("Language detection result: ", detectResult.data)
}
is DetectionResult.Error -> {
Log.d("Language detection result: ", detectResult.errorMessage)
}
}
}
To get the confidence values of a string's most likely languages, pass the string to the detectPossibleLanguages() method.
languageDetector.detectPossibleLanguages("sourceText"){ detectResult ->
when(detectResult){
is DetectionResult.Success -> {
detectResult.data.forEach { possibleLanguage ->
Log.d("Language detection result: ", "${possibleLanguage.langCode} - ${possibleLanguage.confidence}")
}
}
is DetectionResult.Error -> {
Log.d("Language detection result: ", detectResult.errorMessage)
}
}
}
The image classification service classifies elements in images into intuitive categories, such as people, objects, environments, activities, or artwork, to define image themes and application scenarios.
You can configure your app to automatically download the model to the device after your app is installed from the Play Store or AppGallery. Add the following statements to the AndroidManifest.xml file.
<manifest
...
<meta-data
android:name="com.huawei.hms.ml.DEPENDENCY"
android:value= "label"/>
<meta-data
android:name="com.google.mlkit.vision.DEPENDENCIES"
android:value="ica" >
...
</manifest>
First, get the instance of image classification by calling ImageClassification.getClient(....)
The function takes context
and confidence threshold
as parameters. The confidence threshold
can be null. If you give a confidence threshold, ML Kit will use the minimum confidence threshold for image classification, otherwise it will use the default ML Kit settings.
val imageClassification = ImageClassification.getClient(context,confidenceThreshold?)
To classify the image, pass the bitmap to the analyseImage() method.
imageClassification.analyseImage(bitmap){ classificationResult ->
when(classificationResult){
is ClassificationResult.Success -> {
Log.d("Image Classification result: ", classificationResult.data)
}
is ClassificationResult.Error -> {
Log.d("Image Classification result: ", classificationResult.errorMessage)
}
}
}
This library provides AccountService interface to handle Google Account Service and Huawei Account Kit with single code base.
First, initialize AccountService
:
val accountService = AccountService.Factory.create(
context,
SignInParams.Builder()
.requestEmail()
.create()
)
It needs Context
to check mobile services availability and provide proper mobile service type. Needs SignInParams
to get permission from user to get extra information like email.
Then call silentSignIn
to get last signed account. If result is success and there is no signed account it returns null
.
accountService.silentSignIn(object : ResultCallback<SignInUser>{
override fun onSuccess(result: SignInUser?) {}
override fun onFailure(error: Exception) {}
override fun onCancelled() {}
})
Call getSignInIntent
to start the Activity
of the relevant service for the use login.
accountService.getSignInIntent { intent ->
startActivityForResult(intent, REQUEST_CODE)
}
Then get result from signInIntent by calling onSignInActivityResult
. Call this function in the onActivityResult
.
accountService.onSignInActivityResult(intent,
object: ResultCallback<SignInUser> {
override fun onSuccess(result: SignInUser?) {}
override fun onFailure(error: Exception) {}
override fun onCancelled() {}
}
)
Call signOut
to sign out of the account.
accountService.signOut()
.addOnSuccessListener {}
.addOnFailureListener {}
.addOnCanceledListener {}
This library provides AuthService interface to handle Firebase Auth Service and AGC Auth Service with single code base.
First, initialize AuthService
:
val authService = AuthService.Factory.create(context)
It needs Context
to check mobile services availability and provide proper mobile service type.
Then get last signed user by calling getUser()
. If there is no signed user it will return null
Call signInWithFacebook
to sign in with facebook account. It needs token which you get from facebook sdk. If it is success, it returns AuthUser
.
authService.signInWithFacebook(token)
.addOnSuccessListener {authUser -> }
.addOnFailureListener {}
Call signInWithGoogleOrHuawei
to sign in with google or huawei account. It needs token which you get from account sdk. If it is success, it returns AuthUser
.
authService.signInWithGoogleOrHuawei(token)
.addOnSuccessListener {authUser -> }
.addOnFailureListener {}
Call signInWithEmail
to sign in with email. It needs email and password. If it is success, it returns AuthUser
.
authService.signInWithEmail(email, password)
.addOnSuccessListener {authUser -> }
.addOnFailureListener {}
Call signInWithPhone
to sign in with phone. It needs countryCode, phoneNumber, password and verifyCode. If it is success, it returns AuthUser
.
Firebase Auth Service only uses the verifyCode
parameter to login. You can get the verifyCode
using the getPhoneCode
method.
AGC Auth Service uses countryCode
, phoneNumber
and password
parameters to login. In order to use the signInWithPhone
method by the AGC Auth Service, the phone must be registered. You can use the signUpWithPhone
method to register.
authService.signInWithPhone(countryCode,phoneNumber,password,verifyCode)
.addOnSuccessListener {authUser -> }
.addOnFailureListener {}
Call signInWithTwitter
to sign in with twitter. It needs token and secret. If it is success, it returns AuthUser
.
authService.signInWithTwitter(token, secret)
.addOnSuccessListener {authUser -> }
.addOnFailureListener {}
Call anonymousSignIn
to sign in with an anonymous account that generated by Auth Service Server. It doesn't need any information. If it is success, it returns AuthUser
.
authService.anonymousSignIn()
.addOnSuccessListener {authUser -> }
.addOnFailureListener {}
Call signUp
to sign up with email. It needs email and password. If it is success, it returns VerificationType
.
authService.signUp(email, password)
.addOnSuccessListener {verificationType -> }
.addOnFailureListener {}
If VerificationType
is CODE
, it means that an e-mail containing verification code has been sent to the user. Call verifyCode
to save user with verification code.
authService.verifyCode(email, password, verificationCode)
.addOnSuccessListener {}
.addOnFailureListener {}
Call signUpWithPhone
to sign up to AGC Auth Service with phone. It needs country code, phone number, password and verify code. You can get the verifyCode using the getPhoneCode
method.
This method is only used for AGC Auth Service.
There is no need to register for Firebase Auth Service. You can login directly using the signInWithPhone
method.
authService.signUp(countryCode, phoneNumber, password, verifyCode)
.addOnSuccessListener {}
.addOnFailureListener {}
If VerificationType
is CODE
, it means that an e-mail containing verification code has been sent to the user. Call verifyCode
to save user with verification code.
authService.verifyCode(email, password, verificationCode)
.addOnSuccessListener {}
.addOnFailureListener {}
Call resetPassword
to reset user' s password. It needs email. If it is success, it returns VerificationType
.
authService.resetPassword(email)
.addOnSuccessListener {verificationType -> }
.addOnFailureListener {}
If verification type is LINK
, it means that an e-mail containing link to reset password has been sent to the user. If VerificationType
is CODE
, it means that an e-mail containing verificaton code has been sent to the user. Call verifyCodeToResetPassword
to reset user' s password.
authService.verifyCodeToResetPassword(email, newPassword, verificationCode)
.addOnSuccessListener {}
.addOnFailureListener {}
Call updateUsername
to update user' s username. It needs user login.
authService.updateUsername(email)
.addOnSuccessListener {}
.addOnFailureListener {}
Call updatePhoto
to update user' s photo. It needs user login.
authService.updatePhoto(photo)
.addOnSuccessListener {}
.addOnFailureListener {}
Call getCode
to get verification code. It needs new email or new phone number.
authService.getCode(newEmail)
.addOnSuccessListener {}
.addOnFailureListener {}
authService.getCodePassword(newEmail)
.addOnSuccessListener {}
.addOnFailureListener {}
authService.getPhoneCode(country_code,phone,activity) //country_code ex: like Turkey: +90 then phone: 532xxxxxx
.addOnSuccessListener {}
.addOnFailureListener {}
Call updateEmail
to update user's mail. The e-mail address to be changed is needed. You can get the verifyCode using the getCode
method.
authService.updateEmail(newEmail, verificationCode)
.addOnSuccessListener {}
.addOnFailureListener {}
Note: Only a user who has signed in within 5 minutes can change their email address. If such a requirement is not met, reauthenticate the user and then try again.
Call updatePhone
to update user's phone. It needs phone. You can get the verifyCode using the getPhoneCode
method.
authService.updatePhone(country_code, phone, verificationCode) //country_code ex: like Turkey: +90 then phone: 532xxxxxx
.addOnSuccessListener {}
.addOnFailureListener {}
Call updatePasswordWithPhone
to update user's password with phone. You can get the verifyCode using the getPhoneCode
method.
Call updatePasswordWithEmail
to update user's password with email. You can get the verifyCode using the getCode
method.
authService.updatePasswordWithPhone(password, verificationCode)
.addOnSuccessListener {}
.addOnFailureListener {}
authService.updatePasswordWithEmail(password, verificationCode)
.addOnSuccessListener {}
.addOnFailureListener {}
Call linkWithTwitter
to link account with twitter. It needs token and secret. If it is success, it returns AuthUser
.
authService.linkWithTwitter(token, secret)
.addOnSuccessListener {authUser -> }
.addOnFailureListener {}
Call linkWithFacebook
to link account with facebook. It needs token. If it is success, it returns AuthUser
.
authService.linkWithFacebook(token)
.addOnSuccessListener {authUser -> }
.addOnFailureListener {}
Call linkWithEmail
to link account with email. It needs email, password and verifyCode. If it is success, it returns AuthUser
.
authService.linkWithEmail(email,password,verifyCode)
.addOnSuccessListener {authUser -> }
.addOnFailureListener {}
Call linkWithPhone
to link account with phone. It needs countryCode, phoneNumber, password and verifyCode. If it is success, it returns AuthUser
.
authService.linkWithPhone(countryCode,phoneNumber,password,verifyCode)
.addOnSuccessListener {authUser -> }
.addOnFailureListener {}
Call unlink
to unlink account from the linked account. It needs provider. If it is success, it returns AuthUser
.
authService.unlink(provider)
.addOnSuccessListener {authUser -> }
.addOnFailureListener {}
Call reAuthenticate
to re-authenticate users. It needs email and password.
authService.reAuthenticate(email,password)
.addOnSuccessListener {}
.addOnFailureListener {}
Call deleteUser
to delete users. It needs email and password.
authService.deleteUser()
.addOnSuccessListener {}
.addOnFailureListener {}
This library includes both Huawei and Google services, allowing you to make your application more secure. This library, it performs necessary checks about whether users are fake users and device security. Click here for view service introduction and more description about Safety Detect Kit features.
You need to initialize SafetyService
interface as follows;
To check if the user is a fake user, you need to call the userDetect
method; Appkey value is app id value in Huawei services. In Google services the app key value is SITE_API_KEY. You can create SITE_API_KEY value from reCAPTCHA Admin Console. Click here
private var safetyService : SafetyService ?= null
override fun onCreate(savedInstanceState: Bundle?) {
safetyService = SafetyService.Factory.create(applicationContext)
safetyService?.userDetect(appKey, object: ResultCallback<SafetyServiceResponse>{
override fun onSuccess(result: SafetyServiceResponse?) {
if(result!= null){
Log.d("CMS", result.responseToken)
}
}
override fun onFailure(error: Exception) {
Log.e("CMS", error.toString())
}
override fun onCancelled() {
TODO("Not yet implemented")
}})
In this library, you need to call the rootDetection
method to check whether the device is safe or not. Appkey value is app id value in Huawei services. In Google services the app key value is API_KEY. You can create API_KEY value from Google APIs Console. Click here
override fun onCreate(savedInstanceState: Bundle?){
safetyService = SafetyService.Factory.create(applicationContext)
safetyService?.rootDetection(appKey, object: ResultCallback<RootDetectionResponse> {
override fun onSuccess(result: RootDetectionResponse?) {
if(result!=null){
if(result.basicIntegrity){
Log.d("CMS", result.toString())
}
}else{
Log.d( "CMS","You need to install Google or Huawei Mobile Services to run application.")
}
}
override fun onFailure(error: Exception) {
Log.e("CMS", error.toString())
}
override fun onCancelled() {
TODO("Not yet implemented")
}})
With the AppChecks feature, you can easily and quickly detect harmful applications on your device.
You can check whether the AppChecks feature is active on your device with the isAppChecksEnabled()
method.
fun isAppChecksEnabled(callback: ResultCallback<CommonVerifyAppChecksEnabledRes>)
safetyService.isAppChecksEnabled(object: ResultCallback<CommonVerifyAppChecksEnabledRes>{
override fun onSuccess(appsCheckResp: CommonVerifyAppChecksEnabledRes?) {
if(appsCheckResp!=null){
val result = appsCheckResp.result
if(result){
Log.d("CMS", "App Checks is enabled")
}else{
Log.d("CMS", "App Checks is disabled")
}
}
}
override fun onFailure(e: Exception) {
Log.e("CMS", "App Checks Fail: ${e.message}")
}
})
If the App Checks feature is disabled, you can enable it with the enableAppsCheck()
method.
fun enableAppsCheck(callback: ResultCallback<CommonVerifyAppChecksEnabledRes>)
safetyService.enableAppsCheck(object: ResultCallback<CommonVerifyAppChecksEnabledRes>{
override fun onSuccess(appsCheckResp: CommonVerifyAppChecksEnabledRes?) {
if(appsCheckResp!=null){
val result = appsCheckResp.result
if(result){
Log.d("CMS", "App Checks enabled")
}else{
Log.d("CMS", "App Checks not enabled")
}
}
}
override fun onFailure(e: Exception) {
Log.e("CMS", "App Checks Fail: ${e.message}")
}
})
You can detect malicious applications on your device with the getMaliciousAppsList()
method.
fun getMaliciousAppsList(callback: ResultCallback<CommonMaliciousAppResponse>)
safetyService.getMaliciousAppsList(object: ResultCallback<CommonMaliciousAppResponse>{
override fun onSuccess(maliciousAppResponse: CommonMaliciousAppResponse?){
if (maliciousAppResponse != null) {
val appList = maliciousAppResponse.getMaliciousAppsList
if (appList?.isNotEmpty() == true){
Log.e("CMS", "Potentially harmful apps are installed!")
for (harmfulApp in appList){
Log.e("CMS", "Information about a harmful app:")
Log.e("CMS", " APK: ${harmfulApp.apkPackageName}")
Log.e("CMS", " SHA-256: ${harmfulApp.apkSha256}")
Log.e("CMS", " Category: ${harmfulApp.apkCategory}")
}
}else{
Log.d("CMS", "There are no known harmful apps installed.")
}
}
}
override fun onFailure(e: Exception){
Log.e("CMS", "Error code: ${e.localizedMessage} -- Message: ${e.message}")
}
})
You can check whether URL addresses are safe with the URLCheck feature.
To activate the URLCheck feature, you must first call the initURLCheck()
method.
fun initURLCheck():Work<Unit>
safetyService.initURLCheck().addOnSuccessListener{
Log.d("CMS", "Url checks activated")
}.addOnFailureListener{
Log.e("CMS", "Url check fail: ${it.message}")
}
You can check whether the URL you will specify is safe with the urlCheck()
method.
fun urlCheck(url:String,appKey: String,threatType:Int,callback:ResultCallback<CommonUrlCheckRes>)
Appkey value is app id value in Huawei services. In Google services the app key value is API_KEY. You can create API_KEY value from Google APIs Console. Click here You need to activate the SafeBrowsing API feature. You can create new API_KEY from the Credentials tab.
val url = "https://github.com/Explore-In-HMS/common-mobile-services"
safetyService.urlCheck(url,appKey,CommonUrlCheckThreat().urlThreatType(this,CommonUrlCheckThreat.MALWARE_APPLICATIONS),object:ResultCallback<CommonUrlCheckRes>{
override fun onSuccess(appsCheckResp: CommonUrlCheckRes?) {
if(appsCheckResp!=null){
val result = appsCheckResp.urlCheckThreats
if(result!!.isNotEmpty()){
for(urlLists in result){
Log.d("CMS", "URL Check result: ${urlLists.urlCheckResult}")
}
}else{
Log.d("CMS", "No threads found")
}
}
}
override fun onFailure(e: Exception) {
Log.e("CMS", "URLCheck fail : ${e.message}")
}
})
You can use the shutDownUrlCheck()
method to disable the URLCheck feature.
fun shutDownUrlCheck(): Work<Unit>
safetyService.shutDownUrlCheck().addOnSuccessListener{
Log.d("CMS", "Url check is disabled")
}.addOnFailureListener {
Log.e("CMS", "URLCheck fail: ${it.message}")
}
This library includes both Huawei and Google services, allowing you to make your application more secure. This library, it performs Crash Service. Click here for view service introduction and more description about Crash Kit features.
First of all, you have to add root gradle 'classpath 'com.google.firebase:firebase-crashlytics-gradle:2.5.2'' & app gradle 'apply plugin: 'com.google.firebase.crashlytics'';
val crashService = CrashService.Factory.create(context)
It needs Context
to check mobile services availability and provide proper mobile service type.
//You can reach just write with "crashService." all of functions:
testIt(context: Context)
log(var1: String)
log(var1: Int, var2: String)
setCustomKey(var1: String, var2: String)
setCustomKey(var1: String, var2: Boolean)
setCustomKey(var1: String, var2: Double)
setCustomKey(var1: String, var2: Float)
setCustomKey(var1: String, var2: Int)
setCustomKey(var1: String, var2: Long)
setCustomKeys(var1: CustomKeysAndValues)
setUserId(var1: String)
recordException(var1: Throwable)
enableCrashCollection(enable: Boolean)
HMS Push Kit is messaging service. Push Kit helps you quickly and efficiently reach users. By integrating Push Kit, you can send messages to your apps on users' devices in real time. Click here for view service introduction and more description about Push Kit features.
First of all, you have to create Services extends by HMS and GMS Messaging;
class HMSPushService : HmsMessageService() {
val TAG = "HMS_PUSH"
override fun onNewToken(token: String?) {
super.onNewToken(token)
Log.i(TAG, "Token: $token")
}
override fun onMessageReceived(message: RemoteMessage?) {
super.onMessageReceived(message)
Log.i(TAG, "Remote Message: ${message?.data}")
}
}
class GMSPushService : FirebaseMessagingService() {
val TAG = "GMS_PUSH"
override fun onNewToken(token: String?) {
super.onNewToken(token)
Log.i(TAG, "Token: $token")
}
override fun onMessageReceived(message: RemoteMessage?) {
super.onMessageReceived(message)
Log.i(TAG, "Remote Message: ${message?.data}")
}
}
After that you have to add your services into AndroidManifest.xml file and don't forget to add meta-data lines for auto init enabled;
<!-- HMS Push Service -->
<service android:name="com.hms.lib.commonmobileservices.push.basic.services.HMSPushService" android:exported="false">
<intent-filter>
<action android:name="com.huawei.push.action.MESSAGING_EVENT" />
</intent-filter>
</service>
<meta-data
android:name="push_kit_auto_init_enabled"
android:value="true" />
<!-- Firebase Push Service -->
<service android:name="com.hms.lib.commonmobileservices.push.basic.services.GMSPushService" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<meta-data
android:name="firebase_messaging_auto_init_enabled"
android:value="true" />
<!-- Common Push Service -->
<receiver android:name="com.hms.lib.commonmobileservices.app.services.CommonPushService"
android:exported="false">
<intent-filter>
<action android:name="com.commonmobileservices.action.MESSAGING_EVENT" />
</intent-filter>
</receiver>
Common Mobile Services provide a slider push notification in Push service. If you want to use that feature you should send data-message like this;
{
"validate_only": false,
"message":
{
"data": "{'slider':'true','header':'This is a header','callToAction':'This is a sentence for call to action','items':[{'title':'Title of Slider 1','image':'https://yuklio.com/f/ph1d1-sample1.jpg','url':'https://url_of_slider_1.com'},{'title':'Title of Slider 2','image':'https://yuklio.com/f/aPmbR-sample2.jpg','url':'https://url_of_slider_2.com'},{'title':'Title of Slider 3','image':'https://yuklio.com/f/SKWB0-sample3.jpg','url':'https://url_of_slider_3.com'}]}",
"token": ["DEVICE_TOKEN"]
}
}
You can use getToken
method to obtain token.
val token = HuaweiPushServiceImpl(this).getToken()
token.addOnSuccessListener {
println("token-> ${it.token}")
}
val token = GooglePushServiceImpl(this).getToken()
token.addOnSuccessListener {
println("token-> ${it.token}")
}
kt subscribeToTopic
method is subscribes to topics in asynchronous mode. The topic messaging function provided by Push Kit allows you to send messages to multiple devices whose users have subscribed to a specific topic.
You can write messages about the topic as required, and Push Kit determines target devices and then sends messages to the devices in a reliable manner.
The name of the topic to subscribe. Must match the following regular expression: "[a-zA-Z0-9-_.~%]{1,900}".
You need to add a listener to listen to the operation result.
HuaweiPushServiceImpl(this).subscribeToTopic("test")
.addOnSuccessListener { result: Unit ->
Log.i(TAG, "OK")
}
.addOnFailureListener { error: Exception ->
error.printStackTrace()
}
.addOnCanceledListener {
Log.i(TAG, "Cancelled")
}
GooglePushServiceImpl(this).subscribeToTopic("test")
.addOnSuccessListener { result: Unit ->
Log.i(TAG, "OK")
}
.addOnFailureListener { error: Exception ->
error.printStackTrace()
}
.addOnCanceledListener {
Log.i(TAG, "Cancelled")
}
kt unsubscribeFromTopic
method is unsubscribes in asynchronous mode from topics that are subscribed to through the subscribe method.
You need to add a listener to listen to the operation result.
HuaweiPushServiceImpl(this).unsubscribeFromTopic("test")
.addOnSuccessListener { result: Unit ->
Log.i(TAG, "OK")
}
.addOnFailureListener { error: Exception ->
error.printStackTrace()
}
.addOnCanceledListener {
Log.i(TAG, "Cancelled")
}
GooglePushServiceImpl(this).unsubscribeFromTopic("test")
.addOnSuccessListener { result: Unit ->
Log.i(TAG, "OK")
}
.addOnFailureListener { error: Exception ->
error.printStackTrace()
}
.addOnCanceledListener {
Log.i(TAG, "Cancelled")
}
kt setAutoInitEnabled
method is sets whether to enable automatic initialization.
If the enable parameter is set to true, the SDK automatically generates an AAID and obtains a token. The token is returned through the kt onNewToken()
callback method.
HuaweiPushServiceImpl(this).autoInitEnabled(true)
GooglePushServiceImpl(this).autoInitEnabled(true)
kt isAutoInitEnabled
method is checks whether automatic initialization is enabled. The default value is false.
HuaweiPushServiceImpl(this).isAutoInitEnabled()
GooglePushServiceImpl(this).isAutoInitEnabled()
This kit provides different functionalities such as nearby search, text search, place details and place autocomplete. You can use these functions for both Google Services using Places API and Huawei Services using Site Kit.
At first we initialize SiteService
interface:
val siteservice = SiteService.Factory.create(Context, huaweiApikey, googleApiKey)
Context
serves to check the mobile services availability and decide what service to run and the apikey
serves to use the services of Site Kit or make the Places API calls.
getNearbyPlaces
is a function that takes parameters like latitude, longitude, query or the keyword to search, hwpoiType which is the poi type you want to search (in case of using Huawei services you should be careful to enter the poi type matching the HW Poi Types from Site Kit eg. “RESTAURANT” instead of “restaurant”), radius of the area you want the results to be focused, language you want the results in, page index and page size, strict bounds to determine whether we want the location bounds to be strict or not.
fun getNearbyPlaces(
siteLat: Double,
siteLng: Double,
keyword: String?,
hwpoiType: String?,
radius: Int?,
language: String?,
pageIndex: Int?,
pageSize: Int?,
strictBounds: Boolean?,
callback: (SiteToReturnResult: ResultData<List<SiteServiceReturn>>) -> Unit
)
getTextSearchPlaces
function uses almost the same parameters and performs search requests based on keyword.
fun getTextSearchPlaces(
query: String,
siteLat: Double?,
siteLng: Double?,
hwpoiType: String?,
radius: Int?,
language: String?,
pageIndex: Int?,
pageSize: Int?,
callback: (SiteToReturnResult: ResultData<List<SiteServiceReturn>>) -> Unit
)
placeSuggestion
function returns a list of autocompleted places based on the keyword you have entered, the location you enter, the radius you want your results to be focused on and the language of them. childrenNode
parameter is only used by the Huawei Service to return information on the children nodes.
fun placeSuggestion(
keyword: String,
siteLat: Double?,
siteLng: Double?,
childrenNode: Boolean?,
areaRadius: Int?,
areaLanguage: String?,
callback: (SiteToReturnResult: ResultData<List<SiteServiceReturn>>) -> Unit
)
getDetailSearch
function is a function used to get the details of a place based on the place's ID.
fun getDetailSearch(
siteID: String,
areaLanguage: String?,
childrenNode: Boolean?,
callback: (SiteToReturnResult: ResultData<SiteServiceReturn>) -> Unit
)
childrenNode
is also only used in case of the Huawei Services.
The results are returned as a data class of SiteServiceReturn
data class SiteServiceReturn (
val id : String?,
val name : String?,
val locationLat : Double?,
val locationLong : Double?,
val phoneNumber : String?,
val formatAddress : String?,
val distance : Double?,
val image : ArrayList<String>?,
val averagePrice : Double?,
val point : Double?,
)
You can reach the data from SiteServiceReturn
as a result from the callback. Final example of how to call a function is given below.
SiteService.Factory.create(Context, HuaweiApikey, GoogleApiKey).getNearbyPlaces(siteLat,siteLng,query,hwpoiType,radius,language,pageIndex,pageSize,strictBounds,
{
it.handleSuccess {
it.data!![0].name //get name of first result of data
}
})
HUAWEI Identity Kit provides unified address management services for users, including adding, editing, deleting, and querying addresses, and enables the users to authorize apps to access their addresses through a single tap on the screen.
Note: Identity Kit just working on HMS devices. GMS Identity service was deprecated.
At first we initialize IdentityServices
interface as like this:
val identityService = IdentityService.Factory.create(context)
Than we can call getUserAddress
function for obtain user's updated and detailed address information:
identityService!!.getUserAddress()
For catch the address details we have to listen onActivityResult
override function with our response code:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
IdentityService.requestCode** -> when (resultCode) {
Activity.RESULT_OK -> {
val userAddress = UserAddressResponse().parseIntent(data)
if (userAddress != null) {
// Do something with user address
println("$userAddress")
} else {
println("userAddress is null")
}
}
Activity.RESULT_CANCELED -> {
}
else -> {
}
}
else -> {
}
}
}
Remote config is a service that allows you to make theme changes or in-app changes according to the situation in your application without the need for any updates.
First of all you should create a xml file as like this:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<remoteconfig>
<value key="testValue">testSituations</value>
</remoteconfig>
</PreferenceScreen>
At first you initialize RemoteConfigService
interface as like this:
val remoteConfig = IRemoteConfigService.Factory.create(context)
Than you can call setDefaultXml
function for define default key-value xml file to service:
remoteConfig.setDefaultXml(R.xml.remote_config)
For fetch the last values on the server side you have to call fetchAndApply
function:
remoteConfig.fetchAndApply({
Toast.makeText(this, "success", Toast.LENGTH_SHORT).show()
},0) // Toast message is to show the callback to the user and 0 is fetch interval time in seconds.
After you fetch and apply the changes you can get them to your local variables with getString(keyValue)
function:
Note: There are 4 getting functions; getString(keyValue), getBoolean(keyValue), getLong(keyValue) and getDouble(keyValue) so you should use the correct one.
var valueFromConsole = remoteConfig.getString("testValue") // testValue is my keyValue which I use it while I am searchin my value with this keyValue.