介绍
在本文中,我们将学习如何将华为机器学习套件和定位套件集成到 Android 应用程序 KnowMyBoard 中。
如果您是本系列的新手,请阅读以下文章。
中级:Android App KnowMyBoard Part -1 中华为 Account Kit 和 Analytics Kit 的集成
ML Kit 提供了一款应用程序,可以轻松利用华为在机器学习方面久经考验的专业知识,支持各行各业的各种人工智能 (AI) 应用。
ML kit 提供各种服务,在这个应用程序中,我们将集成它的文本相关服务,如文本识别、文本检测和文本翻译服务,这有助于实现应用程序的目标。
适用于 Android 的定位工具包 SDK 为 Android 应用程序提供与位置相关的 API。这些API主要涉及融合定位、活动识别、地理围栏、高精度定位、室内定位、地理编码6个功能。该模式适用于手机和华为平板。我们正在使用 Location 工具包来获取用户的位置。
硬件要求
运行 Windows 10 的计算机(台式机或笔记本电脑)。
Android 手机(带有 USB 数据线),用于调试。
Java JDK 1.8 或更高版本。
已安装 Android Studio 软件或 Visual Studio 或 Code。
HMS Core (APK) 4.X 或更高版本
集成步骤
Step 1. 华为开发者账号并在华为开发者网站完成身份验证,参考注册华为ID。
步骤 2. 在 AppGallery Connect 中创建项目
Step 3. 添加HMS Core SDK
让我们开始编码
MainActivity.kt
package com.huawei.hms.knowmyboard.dtse.activity.view
import com.huawei.hms.knowmyboard.dtse.activity.app.MyApplication.Companion.activity
import androidx.appcompat.app.AppCompatActivity
import com.huawei.hms.knowmyboard.dtse.activity.viewmodel.LoginViewModel
import com.huawei.hms.mlsdk.text.MLTextAnalyzer
import android.graphics.Bitmap
import com.huawei.hms.mlsdk.langdetect.local.MLLocalLangDetector
import com.huawei.hms.mlsdk.translate.local.MLLocalTranslator
import android.app.ProgressDialog
import android.os.Bundle
import androidx.lifecycle.ViewModelProvider
import android.content.Intent
import com.huawei.hms.support.account.AccountAuthManager
import com.google.gson.Gson
import com.huawei.hms.common.ApiException
import android.provider.MediaStore
import com.huawei.hms.mlsdk.common.MLFrame
import com.huawei.hms.mlsdk.text.MLText
import com.huawei.hmf.tasks.OnSuccessListener
import com.huawei.hms.mlsdk.langdetect.MLLangDetectorFactory
import com.huawei.hms.mlsdk.langdetect.local.MLLocalLangDetectorSetting
import com.huawei.hmf.tasks.OnFailureListener
import android.content.DialogInterface
import android.net.Uri
import android.util.Log
import androidx.appcompat.app.AlertDialog
import com.huawei.hms.knowmyboard.dtse.R
import com.huawei.hms.knowmyboard.dtse.activity.model.UserData
import com.huawei.hms.mlsdk.common.MLApplication
import com.huawei.hms.mlsdk.translate.local.MLLocalTranslateSetting
import com.huawei.hms.mlsdk.translate.MLTranslatorFactory
import com.huawei.hms.mlsdk.model.download.MLModelDownloadStrategy
import com.huawei.hms.mlsdk.model.download.MLModelDownloadListener
import com.huawei.hms.mlsdk.text.MLLocalTextSetting
import com.huawei.hms.mlsdk.MLAnalyzerFactory
import java.io.IOException
import java.lang.Exception
import java.util.ArrayList
class MainActivity() : AppCompatActivity() {
var loginViewModel: LoginViewModel? = null
private var mTextAnalyzer: MLTextAnalyzer? = null
var imagePath: Uri? = null
var bitmap: Bitmap? = null
var result = ArrayList<String>()
var myLocalLangDetector: MLLocalLangDetector? = null
var myLocalTranslator: MLLocalTranslator? = null
var textRecognized: String? = null
var progressDialog: ProgressDialog? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
loginViewModel = ViewModelProvider(this).get(LoginViewModel::class.java)
activity = this
progressDialog = ProgressDialog(this)
progressDialog!!.setCancelable(false)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
// Process the authorization result to obtain the authorization code from AuthAccount.
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 8888) {
val authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data)
if (authAccountTask.isSuccessful) {
// The sign-in is successful, and the user's ID information and authorization code are obtained.
val authAccount = authAccountTask.result
val userData = UserData()
userData.accessToken = authAccount.accessToken
userData.countryCode = authAccount.countryCode
userData.displayName = authAccount.displayName
userData.email = authAccount.email
userData.familyName = authAccount.familyName
userData.givenName = authAccount.givenName
userData.idToken = authAccount.idToken
userData.openId = authAccount.openId
userData.uid = authAccount.uid
userData.photoUriString = authAccount.avatarUri.toString()
userData.unionId = authAccount.unionId
val gson = Gson()
Log.e("TAG", "sign in success : " + gson.toJson(authAccount))
loginViewModel = ViewModelProvider(this@MainActivity).get(
LoginViewModel::class.java
)
loginViewModel!!.sendData(authAccount.displayName)
progressDialog!!.dismiss()
} else {
// The sign-in failed.
Log.e(
"TAG",
"sign in failed:" + (authAccountTask.exception as ApiException).statusCode
)
progressDialog!!.dismiss()
}
}
if ((requestCode == 2323) && (resultCode == RESULT_OK) && (data != null)) {
progressDialog!!.setMessage("Initializing text detection..")
progressDialog!!.show()
imagePath = data.data
try {
bitmap = MediaStore.Images.Media.getBitmap(this.contentResolver, imagePath)
} catch (e: IOException) {
e.printStackTrace()
Log.e("TAG", " BITMAP ERROR")
}
Log.d("TAG", "Path " + imagePath!!.path)
try {
val selectedBitmap = MediaStore.Images.Media.getBitmap(contentResolver, imagePath)
asyncAnalyzeText(selectedBitmap)
} catch (e: IOException) {
e.printStackTrace()
progressDialog!!.dismiss()
}
}
}
private fun asyncAnalyzeText(bitmap: Bitmap) {
if (mTextAnalyzer == null) {
createMLTextAnalyzer()
}
val frame = MLFrame.fromBitmap(bitmap)
val task = mTextAnalyzer!!.asyncAnalyseFrame(frame)
task.addOnSuccessListener(object : OnSuccessListener<MLText> {
override fun onSuccess(text: MLText) {
progressDialog!!.setMessage("Initializing language detection..")
Log.d("TAG", "#==>" + text.stringValue)
textRecognized = text.stringValue.trim { it <= ' ' }
if (!textRecognized!!.isEmpty()) {
// Create a local language detector.
val factory = MLLangDetectorFactory.getInstance()
val setting =
MLLocalLangDetectorSetting.Factory() // Set the minimum confidence threshold for language detection.
.setTrustedThreshold(0.01f)
.create()
myLocalLangDetector = factory.getLocalLangDetector(setting)
val firstBestDetectTask = myLocalLangDetector?.firstBestDetect(textRecognized)
firstBestDetectTask?.addOnSuccessListener(OnSuccessListener { languageDetected ->
progressDialog!!.setMessage("Initializing text translation..")
// Processing logic for detection success.
Log.d("TAG", "Lang detect :$languageDetected")
textTranslate(languageDetected, textRecognized!!, bitmap)
})?.addOnFailureListener(object : OnFailureListener {
override fun onFailure(e: Exception) {
// Processing logic for detection failure.
Log.e("TAG", "Lang detect error:" + e.message)
}
})
} else {
progressDialog!!.dismiss()
showErrorDialog("Failed to recognize text.")
}
}
}).addOnFailureListener(object : OnFailureListener {
override fun onFailure(e: Exception) {
Log.e("TAG", "#==>" + e.message)
}
})
}
private fun showErrorDialog(msg: String) {
val alertDialog = AlertDialog.Builder(this).create()
alertDialog.setTitle("Error")
alertDialog.setMessage(msg)
alertDialog.setButton(
AlertDialog.BUTTON_POSITIVE,
"OK",
object : DialogInterface.OnClickListener {
override fun onClick(dialog: DialogInterface, which: Int) {
dialog.dismiss()
}
})
alertDialog.show()
}
private fun textTranslate(languageDetected: String, textRecognized: String, uri: Bitmap) {
MLApplication.initialize(application)
MLApplication.getInstance().apiKey =
"DAEDAF48ZIMI4ettQdTfCKlXgaln/E+TO/PrsX+LpP2BubkmED/iC0iVEps5vfx1ol27rHvuwiq64YphpPkGYWbf9La8XjnvC9qhwQ=="
// Create an offline translator.
val setting =
MLLocalTranslateSetting.Factory() // Set the source language code. The ISO 639-1 standard is used. This parameter is mandatory. If this parameter is not set, an error may occur.
.setSourceLangCode(languageDetected) // Set the target language code. The ISO 639-1 standard is used. This parameter is mandatory. If this parameter is not set, an error may occur.
.setTargetLangCode("en")
.create()
myLocalTranslator = MLTranslatorFactory.getInstance().getLocalTranslator(setting)
// Set the model download policy.
val downloadStrategy = MLModelDownloadStrategy.Factory()
.needWifi() // It is recommended that you download the package in a Wi-Fi environment.
.create()
// Create a download progress listener.
val modelDownloadListener: MLModelDownloadListener = object : MLModelDownloadListener {
override fun onProcess(alreadyDownLength: Long, totalLength: Long) {
runOnUiThread(object : Runnable {
override fun run() {
// Display the download progress or perform other operations.
}
})
}
}
myLocalTranslator?.preparedModel(downloadStrategy, modelDownloadListener)
?.addOnSuccessListener(object : OnSuccessListener<Void?> {
override fun onSuccess(aVoid: Void?) {
// Called when the model package is successfully downloaded.
// input is a string of less than 5000 characters.
val task = myLocalTranslator?.asyncTranslate(textRecognized)
// Before translation, ensure that the models have been successfully downloaded.
task?.addOnSuccessListener(object : OnSuccessListener<String> {
override fun onSuccess(translated: String) {
// Processing logic for detection success.
result.clear()
result.add(languageDetected.trim { it <= ' ' })
result.add(textRecognized.trim { it <= ' ' })
result.add(translated.trim { it <= ' ' })
loginViewModel!!.setImage(uri)
loginViewModel!!.setTextRecognized(result)
progressDialog!!.dismiss()
}
})?.addOnFailureListener(object : OnFailureListener {
override fun onFailure(e: Exception) {
// Processing logic for detection failure.
progressDialog!!.dismiss()
}
})
}
})?.addOnFailureListener(object : OnFailureListener {
override fun onFailure(e: Exception) {
// Called when the model package fails to be downloaded.
progressDialog!!.dismiss()
}
})
}
private fun createMLTextAnalyzer() {
val setting = MLLocalTextSetting.Factory()
.setOCRMode(MLLocalTextSetting.OCR_DETECT_MODE)
.create()
mTextAnalyzer = MLAnalyzerFactory.getInstance().getLocalTextAnalyzer(setting)
}
override fun onStop() {
if (myLocalLangDetector != null) {
myLocalLangDetector!!.stop()
}
if (myLocalTranslator != null) {
myLocalTranslator!!.stop()
}
if (progressDialog != null) {
progressDialog!!.dismiss()
}
super.onStop()
}
}
LoginViewModel.kt
package com.huawei.hms.knowmyboard.dtse.activity.viewmodel
import android.app.Application
import com.huawei.hms.knowmyboard.dtse.activity.app.MyApplication.Companion.activity
import androidx.lifecycle.AndroidViewModel
import com.huawei.hms.support.account.service.AccountAuthService
import androidx.lifecycle.MutableLiveData
import android.graphics.Bitmap
import android.util.Log
import android.view.View
import com.huawei.hms.location.LocationResult
import androidx.lifecycle.LiveData
import android.widget.Toast
import com.huawei.hms.support.account.request.AccountAuthParams
import com.huawei.hms.support.account.request.AccountAuthParamsHelper
import com.huawei.hms.support.account.AccountAuthManager
import com.huawei.hms.common.ApiException
import java.util.ArrayList
class LoginViewModel(application: Application) : AndroidViewModel(application) {
var service: AccountAuthService? = null
private val message = MutableLiveData<String>()
val textRecongnized = MutableLiveData<ArrayList<String>>()
val imagePath = MutableLiveData<Bitmap>()
val locationResult = MutableLiveData<LocationResult>()
fun sendData(msg: String) {
message.value = msg
}
fun getMessage(): LiveData<String> {
return message
}
fun setImage(imagePath: Bitmap) {
this.imagePath.value = imagePath
}
fun setLocationResult(locationResult: LocationResult) {
this.locationResult.value = locationResult
}
fun setTextRecognized(textRecognized: ArrayList<String>) {
this.textRecongnized.value = textRecognized
}
fun logoutHuaweiID() {
if (service != null) {
service!!.signOut()
sendData("KnowMyBoard")
Toast.makeText(getApplication(), "You are logged out from Huawei ID", Toast.LENGTH_LONG)
.show()
}
}
fun loginClicked(view: View?) {
val authParams =
AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM).setAuthorizationCode()
.createParams()
service = AccountAuthManager.getService(activity, authParams)
activity!!.startActivityForResult(service?.signInIntent, 8888)
}
fun cancelAuthorization() {
if (service != null) {
// service indicates the AccountAuthService instance generated using the getService method during the sign-in authorization.
service!!.cancelAuthorization().addOnCompleteListener { task ->
if (task.isSuccessful) {
// Processing after a successful authorization cancellation.
Log.i("TAG", "onSuccess: ")
sendData("KnowMyBoard")
Toast.makeText(getApplication(), "Cancelled authorization", Toast.LENGTH_LONG)
.show()
} else {
// Handle the exception.
val exception = task.exception
if (exception is ApiException) {
val statusCode = exception.statusCode
Log.i("TAG", "onFailure: $statusCode")
Toast.makeText(
getApplication(),
"Failed to cancel authorization",
Toast.LENGTH_LONG
).show()
}
}
}
} else {
Toast.makeText(getApplication(), "Login required", Toast.LENGTH_LONG).show()
}
}
fun onClickScan() {
Log.d("TAG", "...Scan...")
}
}
RequestLocationData.kt
package com.huawei.hms.knowmyboard.dtse.activity.util
import android.Manifest
import androidx.fragment.app.FragmentActivity
import com.huawei.hms.knowmyboard.dtse.activity.viewmodel.LoginViewModel
import android.app.Activity
import android.content.Context
import com.huawei.hmf.tasks.OnSuccessListener
import com.huawei.hms.knowmyboard.dtse.activity.util.RequestLocationData
import com.huawei.hmf.tasks.OnFailureListener
import android.os.Build
import androidx.core.app.ActivityCompat
import android.content.pm.PackageManager
import com.google.gson.Gson
import android.os.Looper
import android.location.Geocoder
import android.util.Log
import com.huawei.hms.location.*
import java.io.IOException
import java.lang.StringBuilder
import java.util.*
class RequestLocationData(
context: Context?,
activity: FragmentActivity?,
loginViewModel: LoginViewModel?
) {
var settingsClient: SettingsClient? = null
private var isLocationSettingSuccess = 0
private var myLocationRequest: LocationRequest? = null
// Define a fusedLocationProviderClient object.
private var fusedLocationProviderClient: FusedLocationProviderClient? = null
var myLocationCallback: LocationCallback? = null
var context: Context? = null
var activity: Activity? = null
var locationResult: LocationResult? = null
var loginViewModel: LoginViewModel? = null
fun initFusionLocationProviderClint() {
// Instantiate the fusedLocationProviderClient object.
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(activity)
settingsClient = LocationServices.getSettingsClient(activity)
}
fun checkDeviceLocationSettings() {
val builder = LocationSettingsRequest.Builder()
myLocationRequest = LocationRequest()
builder.addLocationRequest(myLocationRequest)
val locationSettingsRequest = builder.build()
// Check the device location settings.
settingsClient!!.checkLocationSettings(locationSettingsRequest) // Define the listener for success in calling the API for checking device location settings.
.addOnSuccessListener { locationSettingsResponse: LocationSettingsResponse ->
val locationSettingsStates = locationSettingsResponse.locationSettingsStates
val stringBuilder = StringBuilder()
// Check whether the location function is enabled.
stringBuilder.append(",\nisLocationUsable=")
.append(locationSettingsStates.isLocationUsable)
// Check whether HMS Core (APK) is available.
stringBuilder.append(",\nisHMSLocationUsable=")
.append(locationSettingsStates.isHMSLocationUsable)
Log.i(TAG, "checkLocationSetting onComplete:$stringBuilder")
// Set the location type.
myLocationRequest!!.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
// Set the number of location updates to 1.
myLocationRequest!!.numUpdates = 1
isLocationSettingSuccess = 1
} // Define callback for failure in checking the device location settings.
.addOnFailureListener { e -> Log.i(TAG, "checkLocationSetting onFailure:" + e.message) }
}
fun checkPermission() {
// Dynamically apply for required permissions if the API level is 28 or lower.
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
Log.i(TAG, "android sdk <= 28 Q")
if (ActivityCompat.checkSelfPermission(
context!!,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(
context!!,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
val strings = arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.MANAGE_MEDIA,
Manifest.permission.MEDIA_CONTENT_CONTROL,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
ActivityCompat.requestPermissions(activity!!, strings, 1)
}
} else {
// Dynamically apply for the android.permission.ACCESS_BACKGROUND_LOCATION permission in addition to the preceding permissions if the API level is higher than 28.
if (ActivityCompat.checkSelfPermission(
activity!!,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
context!!,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
context!!,
"android.permission.ACCESS_BACKGROUND_LOCATION"
) != PackageManager.PERMISSION_GRANTED
) {
val strings = arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.MEDIA_CONTENT_CONTROL,
Manifest.permission.MANAGE_MEDIA,
"android.permission.ACCESS_BACKGROUND_LOCATION"
)
ActivityCompat.requestPermissions(activity!!, strings, 2)
}
}
}
fun refreshLocation(): LocationResult? {
Log.d(TAG, "Refreshing location")
if (isLocationSettingSuccess == 1) {
myLocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
if (locationResult != null) {
val gson = Gson()
Log.d(
TAG,
" Location data :" + locationResult.lastLocation.latitude + " : " + locationResult.lastLocation.longitude
)
Log.d(TAG, " Location data :" + gson.toJson(locationResult.lastHWLocation))
Log.d(TAG, " Location data :" + locationResult.lastHWLocation.countryName)
Log.d(TAG, " Location data :" + locationResult.lastHWLocation.latitude)
Log.d(TAG, " Location data :" + locationResult.lastHWLocation.longitude)
// binding.textDetected.setText("Latitude " + locationResult.getLastHWLocation().getLatitude() + " Longitude " + locationResult.getLastHWLocation().getLongitude());
getGeoCoderValues(
locationResult.lastHWLocation.latitude,
locationResult.lastHWLocation.longitude
)
//locationResult = locationResult1;
loginViewModel!!.setLocationResult(locationResult)
}
}
}
fusedLocationProviderClient!!.requestLocationUpdates(
myLocationRequest,
myLocationCallback,
Looper.getMainLooper()
)
} else {
Log.d(TAG, "Failed to get location settings")
}
return locationResult
}
fun disableLocationData() {
fusedLocationProviderClient!!.disableBackgroundLocation()
fusedLocationProviderClient!!.removeLocationUpdates(myLocationCallback)
}
private fun getGeoCoderValues(latitude: Double, longitude: Double) {
getAddress(context, latitude, longitude)
/* Geocoder geocoder;
List<Address> addresses;
Locale locale = new Locale("en", "IN");
geocoder = new Geocoder(getContext(), locale);
try {
addresses = geocoder.getFromLocation(latitude, longitude, 1); // Here 1 represent max location result to returned, by documents it recommended 1 to 5
Gson gson=new Gson();
Log.d(TAG,"Geo coder :"+gson.toJson(addresses));
String address = addresses.get(0).getAddressLine(0); // If any additional address line present than only, check with max available address lines by getMaxAddressLineIndex()
String city = addresses.get(0).getLocality();
String state = addresses.get(0).getAdminArea();
String country = addresses.get(0).getCountryName();
String postalCode = addresses.get(0).getPostalCode();
String knownName = addresses.get(0).getFeatureName();
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG,"Error while fetching Geo coder :"+e.getMessage());
}*/
/* Locale locale = new Locale("en", "IN");
GeocoderService geocoderService =
LocationServices.getGeocoderService(getActivity().getBaseContext(), locale);
// Request reverse geocoding.
GetFromLocationRequest getFromLocationRequest = new GetFromLocationRequest(latitude, longitude, 5);
// Initiate reverse geocoding.
geocoderService.getFromLocation(getFromLocationRequest)
.addOnSuccessListener(hwLocation -> {
Gson gson=new Gson();
Log.d(TAG,"Geo coder :"+gson.toJson(hwLocation));
})
.addOnFailureListener(e -> {
Log.e(TAG,"Error while fetching Geo coder :"+e.getMessage());
});*/
}
companion object {
var TAG = "TAG"
fun getAddress(context: Context?, LATITUDE: Double, LONGITUDE: Double) {
//Set Address
try {
val geocoder = Geocoder(context, Locale.getDefault())
val addresses = geocoder.getFromLocation(LATITUDE, LONGITUDE, 1)
if (addresses != null && addresses.size > 0) {
val address =
addresses[0].getAddressLine(0) // If any additional address line present than only, check with max available address lines by getMaxAddressLineIndex()
val city = addresses[0].locality
val state = addresses[0].adminArea
val country = addresses[0].countryName
val postalCode = addresses[0].postalCode
val knownName = addresses[0].featureName // Only if available else return NULL
Log.d(TAG, "getAddress: address$address")
Log.d(TAG, "getAddress: city$city")
Log.d(TAG, "getAddress: state$state")
Log.d(TAG, "getAddress: postalCode$postalCode")
Log.d(TAG, "getAddress: knownName$knownName")
}
} catch (e: IOException) {
e.printStackTrace()
Log.e(TAG, "Error while fetching Geo coder :" + e.message)
}
}
}
init {
this.context = context
this.activity = activity
this@RequestLocationData.loginViewModel = loginViewModel
}
}
LoginFragment.kt
package com.huawei.hms.knowmyboard.dtse.activity.fragments
import com.huawei.hms.knowmyboard.dtse.activity.viewmodel.LoginViewModel
import androidx.navigation.Navigation.findNavController
import android.content.SharedPreferences
import androidx.navigation.NavController
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModelProvider
import android.annotation.SuppressLint
import android.content.Context
import android.util.Log
import android.view.*
import androidx.fragment.app.Fragment
import com.huawei.hms.knowmyboard.dtse.R
import java.lang.Exception
class LoginFragment : Fragment() {
var loginBinding: FragmentLoginBinding? = null
var loginViewModel: LoginViewModel? = null
var menu: Menu? = null
var prefs: SharedPreferences? = null
var editor: SharedPreferences.Editor? = null
var navController: NavController? = null
private val MY_PREF_NAME = "my_pref_name"
private val TAG = "TAG"
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
navController = findNavController(view)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
loginBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_login, container, false)
loginViewModel = ViewModelProvider(requireActivity()).get(LoginViewModel::class.java)
loginBinding?.loginViewModel = loginViewModel
Log.d(TAG, " Pref $preferenceValue")
if (preferenceValue == "user_name") {
loginBinding?.btnHuaweiIdAuth?.visibility = View.VISIBLE
} else {
enableMenu(menu)
requireActivity().title = preferenceValue
loginBinding?.btnHuaweiIdAuth?.visibility = View.GONE
}
loginBinding?.imageLogo?.setOnClickListener { v: View? -> navController!!.navigate(R.id.action_loginFragment_to_mainFragment) }
loginViewModel!!.getMessage().observeForever { message ->
updateMessage(message)
if (message != resources.getString(R.string.app_name)) {
preferenceValue = message
enableMenu(menu)
loginBinding?.btnHuaweiIdAuth?.visibility = View.GONE
} else {
disableMenu(menu)
loginBinding?.btnHuaweiIdAuth?.visibility = View.VISIBLE
preferenceValue = "user_name"
}
}
return loginBinding?.root
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
menu.clear()
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.main, menu)
this.menu = menu
disableMenu(menu)
}
private fun disableMenu(menu: Menu?) {
try {
if (menu != null) {
if (preferenceValue == "user_name") {
menu.findItem(R.id.menu_login_logout).isVisible = false
menu.findItem(R.id.menu_cancel_auth).isVisible = false
requireActivity().title = resources.getString(R.string.app_name)
} else {
menu.findItem(R.id.menu_login_logout).isVisible = true
menu.findItem(R.id.menu_cancel_auth).isVisible = true
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun enableMenu(menu: Menu?) {
try {
menu!!.findItem(R.id.menu_login_logout).isVisible = true
menu.findItem(R.id.menu_cancel_auth).isVisible = true
} catch (e: Exception) {
e.printStackTrace()
}
}
@SuppressLint("NonConstantResourceId")
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.menu_cancel_auth -> {
preferenceValue = "user_name"
loginViewModel!!.cancelAuthorization()
loginBinding!!.btnHuaweiIdAuth.visibility = View.VISIBLE
disableMenu(menu)
return true
}
R.id.menu_login_logout -> {
preferenceValue = "user_name"
loginViewModel!!.logoutHuaweiID()
loginBinding!!.btnHuaweiIdAuth.visibility = View.VISIBLE
disableMenu(menu)
return true
}
else -> {}
}
return super.onOptionsItemSelected(item)
}
private fun updateMessage(msg: String?) {
//loginBinding.txtMessage.setText(msg);
requireActivity().title = msg
}
var preferenceValue: String?
get() {
prefs = requireActivity().getSharedPreferences(MY_PREF_NAME, Context.MODE_PRIVATE)
return prefs?.getString("user_name", "user_name")
}
set(userName) {
editor = requireActivity().getSharedPreferences(MY_PREF_NAME, Context.MODE_PRIVATE).edit()
editor?.putString("user_name", userName)
editor?.apply()
}
}
MainFragment.kt
package com.huawei.hms.knowmyboard.dtse.activity.fragments
import com.huawei.hms.knowmyboard.dtse.activity.viewmodel.LoginViewModel
import com.huawei.hms.knowmyboard.dtse.activity.util.RequestLocationData
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModelProvider
import android.content.Intent
import android.annotation.SuppressLint
import android.util.Log
import android.view.*
import androidx.fragment.app.Fragment
import com.huawei.hms.knowmyboard.dtse.R
import com.huawei.hms.knowmyboard.dtse.databinding.FragmentMainFragmentBinding
import java.lang.Exception
class MainFragment : Fragment() {
var binding: FragmentMainFragmentBinding? = null
var loginViewModel: LoginViewModel? = null
var locationData: RequestLocationData? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
binding =
DataBindingUtil.inflate(inflater, R.layout.fragment_main_fragment, container, false)
// settingsClient = LocationServices.getSettingsClient(getActivity());
loginViewModel = ViewModelProvider(requireActivity()).get(LoginViewModel::class.java)
binding?.loginViewModel = loginViewModel
locationData = RequestLocationData(context, activity, loginViewModel)
locationData!!.initFusionLocationProviderClint()
locationData!!.checkPermission()
locationData!!.checkDeviceLocationSettings()
// checkDeviceLocationSettings();
// Instantiate the fusedLocationProviderClient object.
// fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(getActivity());
binding?.buttonScan?.setOnClickListener {
Log.d(TAG, "*******")
//loginViewModel.setTextRecongnized("");
scan()
}
loginViewModel!!.imagePath.observeForever { bitmap ->
try {
binding?.imageView?.setImageBitmap(bitmap)
} catch (e: Exception) {
e.printStackTrace()
Log.e("TAG", "Error : " + e.message)
}
}
loginViewModel!!.textRecongnized.observeForever { res ->
Log.i("TAG", "OBSERVER : " + "Language : " + getStringResourceByName(
res[0].trim { it <= ' ' }) +
" Detected text : " + res[1].trim { it <= ' ' } +
" Translated text : " + res[2].trim { it <= ' ' })
binding?.textLanguage?.text = "Language : " + getStringResourceByName(res[0])
binding?.textDetected?.text = "Detected text : " + res[1]
binding?.textTranslated?.text = "Translated text : " + res[2]
}
loginViewModel!!.locationResult.observeForever { locationResult ->
binding?.textDetected?.text =
"Latitude " + locationResult.lastHWLocation.latitude + " Longitude " + locationResult.lastHWLocation.longitude
}
return binding?.root
}
private fun getStringResourceByName(aString: String): String {
val packageName = requireActivity().packageName
val resId = resources
.getIdentifier(aString, "string", packageName)
return if (resId == 0) {
aString
} else {
getString(resId)
}
}
private fun scan() {
/* MLTextAnalyzer analyzer = new MLTextAnalyzer.Factory(getContext()).create();
analyzer.setTransactor(new OcrDetectorProcessor());
LensEngine lensEngine = new LensEngine.Creator(getContext(), analyzer)
.setLensType(LensEngine.BACK_LENS)
.applyDisplayDimension(1440, 1080)
.applyFps(30.0f)
.enableAutomaticFocus(true)
.create();
SurfaceView mSurfaceView = new SurfaceView(getContext());
try {
lensEngine.run(mSurfaceView.getHolder());
} catch (IOException e) {
// Exception handling logic.
Log.e(TAG,e.getMessage());
}*/
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "image/*"
requireActivity().startActivityForResult(intent, 2323)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
menu.clear()
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.main_fragment_menu, menu)
}
@SuppressLint("NonConstantResourceId")
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.option_refresh_location -> {
//refreshLocation();
locationData!!.refreshLocation()
return true
}
}
return super.onOptionsItemSelected(item)
}
/* private void checkDeviceLocationSettings() {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
myLocationRequest = new LocationRequest();
builder.addLocationRequest(myLocationRequest);
LocationSettingsRequest locationSettingsRequest = builder.build();
// Check the device location settings.
settingsClient.checkLocationSettings(locationSettingsRequest)
// Define the listener for success in calling the API for checking device location settings.
.addOnSuccessListener(locationSettingsResponse -> {
LocationSettingsStates locationSettingsStates =
locationSettingsResponse.getLocationSettingsStates();
StringBuilder stringBuilder = new StringBuilder();
// Check whether the location function is enabled.
stringBuilder.append(",\nisLocationUsable=")
.append(locationSettingsStates.isLocationUsable());
// Check whether HMS Core (APK) is available.
stringBuilder.append(",\nisHMSLocationUsable=")
.append(locationSettingsStates.isHMSLocationUsable());
Log.i(TAG, "checkLocationSetting onComplete:" + stringBuilder.toString());
// Set the location type.
myLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// Set the number of location updates to 1.
myLocationRequest.setNumUpdates(1);
isLocationSettingSuccess = 1;
})
// Define callback for failure in checking the device location settings.
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
isLocationSettingSuccess = 0;
Log.i(TAG, "checkLocationSetting onFailure:" + e.getMessage());
}
});
}*/
/* private void refreshLocation() {
Log.d(TAG, "Refreshing location");
if (isLocationSettingSuccess == 1) {
myLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult != null) {
Gson gson = new Gson();
Log.d(TAG, " Location data :" + locationResult.getLastLocation().getLatitude() + " : " + locationResult.getLastLocation().getLongitude());
Log.d(TAG, " Location data :" + gson.toJson(locationResult.getLastHWLocation()));
Log.d(TAG, " Location data :" + locationResult.getLastHWLocation().getCountryName());
Log.d(TAG, " Location data :" + locationResult.getLastHWLocation().getLatitude());
Log.d(TAG, " Location data :" + locationResult.getLastHWLocation().getLongitude());
binding.textDetected.setText("Latitude " + locationResult.getLastHWLocation().getLatitude() + " Longitude " + locationResult.getLastHWLocation().getLongitude());
getGeoCoderValues(locationResult.getLastHWLocation().getLatitude(),locationResult.getLastHWLocation().getLongitude());
}
}
};
fusedLocationProviderClient.requestLocationUpdates(myLocationRequest, myLocationCallback, Looper.getMainLooper());
} else {
Log.d(TAG, "Failed to get location settings");
}
}*/
/*private void getGeoCoderValues(double latitude, double longitude) {
Locale locale = new Locale("en", "in");
GeocoderService geocoderService =
LocationServices.getGeocoderService(getActivity().getBaseContext(), locale);
// Request reverse geocoding.
GetFromLocationRequest getFromLocationRequest = new GetFromLocationRequest(latitude, longitude, 5);
// Initiate reverse geocoding.
geocoderService.getFromLocation(getFromLocationRequest)
.addOnSuccessListener(hwLocation -> {
Gson gson=new Gson();
Log.d(TAG,"Geo coder :"+gson.toJson(hwLocation));
})
.addOnFailureListener(e -> {
// TODO: Processing when the API call fails.
Log.e(TAG,"Error while fetching Geo coder :"+e.getMessage());
});
}*/
/* void checkPermission() {
// Dynamically apply for required permissions if the API level is 28 or lower.
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
Log.i(TAG, "android sdk <= 28 Q");
if (ActivityCompat.checkSelfPermission(getContext(),
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(getContext(),
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
String[] strings =
{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.MANAGE_MEDIA,Manifest.permission.MEDIA_CONTENT_CONTROL,Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};
ActivityCompat.requestPermissions(getActivity(), strings, 1);
}
} else {
// Dynamically apply for the android.permission.ACCESS_BACKGROUND_LOCATION permission in addition to the preceding permissions if the API level is higher than 28.
if (ActivityCompat.checkSelfPermission(getActivity(),
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(getContext(),
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(getContext(),
"android.permission.ACCESS_BACKGROUND_LOCATION") != PackageManager.PERMISSION_GRANTED) {
String[] strings = {android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.MEDIA_CONTENT_CONTROL,Manifest.permission.MANAGE_MEDIA,
"android.permission.ACCESS_BACKGROUND_LOCATION"};
ActivityCompat.requestPermissions(getActivity(), strings, 2);
}
}
}*/
override fun onStop() {
super.onStop()
locationData!!.disableLocationData()
}
companion object {
var TAG = "TAG"
}
}
结果

技巧和窍门
确保添加了agconnect-services.json文件。
确保添加了所需的依赖项
确保在 AGC 中启用了 ML 服务
图像具有清晰的文本可见性
结论
在本文中,我们学习了如何将华为定位套件和机器学习套件集成到 Android 应用程序 KnowMyBoard 中。我们还学习了如何使用 HMS ML 服务将图像转换为文本,在我之前的文章中,我写了一篇关于 account kit 的文章,请阅读前一篇文章,该文章可在介绍部分找到。
链接:https://dev.to/hmscommunity/integration-of-huawei-ml-kit-in-knowmyboard-app-using-kotlin-part-2-2ff9
网友评论