During my application execution, how can I get EMUI version?
Is there any system method to get EMUI version?
It is possible through accessing system properties like:
#SuppressLint("PrivateApi")
private fun Any?.readEMUIVersion() : String {
try {
val propertyClass = Class.forName("android.os.SystemProperties")
val method: Method = propertyClass.getMethod("get", String::class.java)
var versionEmui = method.invoke(propertyClass, "ro.build.version.emui") as String
if (versionEmui.startsWith("EmotionUI_")) {
versionEmui = versionEmui.substring(10, versionEmui.length)
}
return versionEmui
} catch (e: ClassNotFoundException) {
e.printStackTrace()
} catch (e: NoSuchMethodException) {
e.printStackTrace()
} catch (e: IllegalAccessException) {
e.printStackTrace()
} catch (e: InvocationTargetException) {
e.printStackTrace()
}
return ""
}
However, this is a private Api and if it is not suitable in your case, you can possibly use this workaround (would work for EMUI 9 and 10, however definitely wouldn't for EMUI 5 or below (~android 7)):
#TargetApi(3)
fun Any?.extractEmuiVersion() : String {
return try {
val line: String = Build.DISPLAY
val spaceIndex = line.indexOf(" ")
val lastIndex = line.indexOf("(")
if (lastIndex != -1) {
line.substring(spaceIndex, lastIndex)
} else line.substring(spaceIndex)
} catch (e: Exception) { "" }
}
Any suggestions how to improve the answer are highly appreciated!
Related
I have an app that in an activity i do heavy animations and play sound i used the below code to play the sound
var musicThread:Thread? = null
fun playSound(sound:Uri) {
musicThread = Thread(Runnable {
try {
sharedPlayer.reset()
sharedPlayer = MediaPlayer.create(MyApplication.appContext,sound)
sharedPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
// sharedPlayer.prepare()
sharedPlayer.setVolume(1f, 1f)
sharedPlayer.setLooping(false)
sharedPlayer.start()
sharedPlayer.setOnCompletionListener {
it.reset()
}
} catch (e: Exception) {
e.printStackTrace()
}
runOnUiThread {
}
})
musicThread?.start()
}
fun stopSound() {
try {
if (sharedPlayer.isPlaying()) {
sharedPlayer.stop()
}
musicThread?.stop()
} catch (e: Exception) {
e.printStackTrace()
}
}
Is there any problem with it ? BTW i call playSound many times with different sound files one by one
From the app context? Do I have to include a permission?
And does it close/reboot the app?
Try this
private fun clearAppData() {
try {
// clearing app data
if (Build.VERSION_CODES.KITKAT <= Build.VERSION.SDK_INT) {
(getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager).clearApplicationUserData() // note: it has a return value!
} else {
val packageName = applicationContext.packageName
val runtime = Runtime.getRuntime()
runtime.exec("pm clear $packageName")
}
} catch (e: java.lang.Exception) {
e.printStackTrace()
}
}
Note: This might kill/close your application after clearing user data
I'm new to coroutines and having a hard time figuring out how to correctly wrap an existing callback in a coroutine.
My goal is to be able to do the following:
lifecycleScope.launch {
withContext(Dispatchers.Main) {
val theResult = getPreRollAd() //1. call this suspending func and wait for result
doSomethingWithResult(theResult) //2. now that the result is returned from AdsWizz API (below), do something with it
}
}
Here is the AdsWizz API call that I'd like to "wrap":
val adReqInterface: AdRequestHandlerInterface = object :
AdRequestHandlerInterface {
override fun onResponseError(error: AdswizzSDKError) {
Timber.e("onResponseError $error")
}
override fun onResponseReady(adResponse: AdResponse) {
Timber.d( "onResponseReadySingleAd")
//this contains the url to the ad, title, etc..
!!!*** I WANT TO RETURN THE adResponse.mediaFile?.source string back to "theResult" variable above (in lifecycleScope.launch {.... )
}
}
try {
AdswizzSDK.getAdsLoader().requestAd(adReqParams, adReqInterface)
} catch (e: IllegalArgumentException) {
Timber.d( "IllegalArgumentException")
} catch (e: SecurityException) {
Timber.d( "SecurityException")
} catch (e: Exception) {
Timber.d( "other exception")
e.printStackTrace()
}
I've tried using suspendCoroutine {... to wrap but nothing is working. Really appreciate someones help re the right way to achieve this.
the right way to do it is to use suspendCancellableCoroutine. It can return a result or can be cancelled with an exception.
suspend fun getPreRollAd(): AdResponse {
return suspendCancellableCoroutine {
...
val adReqInterface: AdRequestHandlerInterface = object : AdRequestHandlerInterface {
override fun onResponseError(error: AdswizzSDKError) {
Timber.e("onResponseError $error")
it.cancel(error)
}
override fun onResponseReady(adResponse: AdResponse) {
Timber.d( "onResponseReadySingleAd")
it.resume(adResponse)
}
}
AdswizzSDK.getAdsLoader().requestAd(adReqParams, adReqInterface)
}
}
viewModelScope.launch {
val result = try {
getPreRollAd()
} catch(e: Throwable) {
null
}
...
}
I'm using retrofit 2.6 with kotlin coroutines to make API call without block the UI thread, I got it work but the app crashes when I switch off the internet connection. The logcat error is: E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-1
Here is my code:
private fun handleIntent(slug: String) {
val service = UtilityMethods.migrationTimeService()
UtilityMethods.showView(loading_view)
UtilityMethods.hideView(network_error_msg)
CoroutineScope(Dispatchers.IO).launch {
val res = service.getPostBySlug(slug)
try {
withContext(Dispatchers.Main) {
//Do something with response e.g show to the UI.
val post = res.body()!!.first()
UtilityMethods.hideView(loading_view)
val title = post.title?.rendered
val content = post.content?.rendered
val imageUrl = post.jetPackFeaturedMediaUrl
title_txtView.text = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
Html.fromHtml(title, Html.FROM_HTML_MODE_COMPACT).toString()
else
Html.fromHtml(title).toString()
content_txtView.loadData(content.toString(), "text/html", "UTF-8")
Picasso.get().load(imageUrl).fit().centerCrop().into(thumbnail_imgview)
}
} catch (e: HttpException) {
UtilityMethods.showView(network_error_msg)
} catch (e: Throwable) {
Toast.makeText(this#PostContentActivity, "Ooops: Something else went wrong", Toast.LENGTH_LONG)
}
}
}
I've got the code working, the new code is:
private fun handleIntent(slug: String) = GlobalScope.launch(Dispatchers.Main) {
val service = UtilityMethods.migrationTimeService()
UtilityMethods.showView(loading_view)
UtilityMethods.hideView(network_error_msg)
try {
val res = withContext(Dispatchers.IO) {
service.getPostBySlug(slug)
}
//Do something with response e.g show to the UI.
val post = res.body()!!.first()
UtilityMethods.hideView(loading_view)
val title = post.title?.rendered
val content = post.content?.rendered
val imageUrl = post.jetPackFeaturedMediaUrl
title_txtView.text = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
Html.fromHtml(title, Html.FROM_HTML_MODE_COMPACT).toString()
else
Html.fromHtml(title).toString()
content_txtView.loadData(content.toString(), "text/html", "UTF-8")
Picasso.get().load(imageUrl).fit().centerCrop().into(thumbnail_imgview)
}
catch (e: HttpException) {
Toast.makeText(this#PostContentActivity, "Exception ${e.message}", Toast.LENGTH_LONG).show()
}catch (e: IOException) {
UtilityMethods.hideView(loading_view)
UtilityMethods.showView(network_error_msg)
} catch (e: Throwable) {
Toast.makeText(this#PostContentActivity, "Ooops: Something else went wrong ${e.message}", Toast.LENGTH_LONG).show()
}
}
So while looking into stacktrace I found that ConnectException is thrown when network is unavailable
And that's how I do it in kotlin and it works for me,
suspend fun<T: Any> safeAPICall(call: suspend () -> Response<T>) : T{
val response = try {
call.invoke()
}
catch (e:java.lang.Exception){
e.printStackTrace()
val message = if( e is ConnectException) "Connection Error" else "Something went wrong. Please try again."
throw IOException(ResponseError(message, 500).convertToJsonString())
}
// When connection is OK
if(response.isSuccessful){
return response.body()!!
}else{
val error = response.errorBody()?.string()
error?.let{
val message = JSONObject(it).optString("message", "Something went wrong")
val responseError = ResponseError(message, response.code())
throw IOException(responseError.convertToJsonString())
}
throw IOException(ResponseError("Something went wrong. Please try again.", 500).convertToJsonString())
}
}
The data class that I use
data class ResponseError(val message:String, val errorCode:Int)
Usage:
try {
val response = safeAPICall {APIClient.planner.viewSites(view.context.authToken)}
}
catch (e:Exception){
view.snack(e.message?.toModel<ResponseError>()?.message?: unspecified_error)
}
Bonus:
inline fun <reified T> JSONObject.toModel(): T? = this.run {
try {
Gson().fromJson<T>(this.toString(), T::class.java)
}
catch (e:java.lang.Exception){ e.printStackTrace(); null }
}
inline fun <reified T> String.toModel(): T? = this.run {
try {
JSONObject(this).toModel<T>()
}
catch (e:java.lang.Exception){ null }
}
Instead of this:
CoroutineScope(Dispatchers.IO).launch {
val res = service.getPostBySlug(slug)
try {
withContext(Dispatchers.Main) {
Try this one:
CoroutineScope(Dispatchers.Main).launch {
val res = service.getPostBySlug(slug)
withContext(Dispatchers.IO) {
try {
wrap your 'try and catch' block code within Dispatchers.IO instead of wraping your Dispatchers.IO with in yout try block
I need to print a image using thermal printer. Now I am able to print text using below code,
private fun printBill() {
Thread {
try {
val sock = Socket("192.168.100.99", 9100)
val oStream = PrintWriter(sock.getOutputStream())
oStream.printf("%-35s %-5s %5s\n", "Jihin Raju", 10.00, 100.00)
oStream.println(charArrayOf(0x1D.toChar(), 0x56.toChar(), 0x41.toChar(), 0x10.toChar()))
oStream.close()
sock.close()
} catch (e: UnknownHostException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
runOnUiThread {
Toast.makeText(this#MainActivity, "Printed ", Toast.LENGTH_SHORT).show()
}
}.start()
}
Is there any way to print image