I want to use intent method for get uri from another activity, but intent.getParcelableExtra is deprecated.if I use
if (SDK_INT >= 33) {
intent.getParcelableExtra("EXTRA_URI", Uri::class.java).let { ueray ->
timeLineView.post({
if (ueray != null) {
setBitmap(ueray)
videoView.setVideoURI(ueray)
}
})
}
}
else {
#Suppress("DEPRECATION")
intent.getParcelableExtra<Uri>("EXTRA_URI").let { ueray ->
timeLineView.post({
if (ueray != null) {
setBitmap(ueray)
videoView.setVideoURI(ueray)
}
})
}
}
this code can google play reject my app? because when in remove (SDK_INT >= 33) statement it shows
Call requires API level 33 (current min is 21): android.content.Intent#getParcelableExtra. Thanks in advance
No, Google will not reject your app if you use deprecated method, especially when using it is a necessity as you have no other choice than to use it on SDK's < 33.
My app uses deprecated methods on lower SDK's when it is an only possibility and the app is fine and accessible on the Google Play Store:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val vibrationEffect = VibrationEffect.createWaveform(
longArrayOf(1000, 1000),
intArrayOf(255, 0),
0
)
vibrator.vibrate(vibrationEffect, vibrationAudioAttributes)
} else {
// deprecated but working on lower SDK's
vibrator.vibrate(longArrayOf(0, 1000, 1000), 0, vibrationAudioAttributes)
}
These are extension functions for Intent and they are backward compatible:
#Suppress("DEPRECATION")
inline fun <reified P : Parcelable> Intent.getParcelable(key: String): P? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
getParcelableExtra(key, P::class.java)
} else {
getParcelableExtra(key)
}
}
#Suppress("DEPRECATION")
inline fun <reified P : Parcelable> Intent.getParcelableArrayList(key: String): ArrayList<P>? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
getParcelableArrayListExtra(key, P::class.java)
} else {
getParcelableArrayListExtra(key)
}
}
#Suppress("DEPRECATION")
inline fun <reified P : Parcelable> Bundle.getParcelableValue(key: String): P? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
getParcelable(key, P::class.java)
} else {
getParcelable(key)
}
}
#Suppress("DEPRECATION")
inline fun <reified P : Parcelable> Bundle.getParcelableArrayListValue(key: String): ArrayList<P>? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
getParcelableArrayList(key, P::class.java)
} else {
getParcelableArrayList(key)
}
}
Instead of the uri put uri.toString() as an extra string.
Quite simple.
I want to add vibration functionality to my app and just wanted to get started with a simple vibration, I tried lots od turtorias but none of them seemed to work
#SuppressLint("NewApi")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val timer_button = findViewById<Button>(R.id.timer_button)
val timer_text: EditText = findViewById<EditText>(R.id.time_text)
val vibrator = getSystemService(VIBRATOR_MANAGER_SERVICE) as VibratorManager
timer_button.setOnClickListener {
//val pattern = longArrayOf(0, 200, 100, 300)
vibrator.getDefaultVibrator().vibrate(VibrationEffect.createOneShot(1000,VibrationEffect.DEFAULT_AMPLITUDE))
Toast.makeText(this, vibrator.getDefaultVibrator().getId().toString(),Toast.LENGTH_SHORT).show()
}}
Also I added the vibration permission to my manifest.xml
<uses-permission android:name="android.permission.VIBRATE" />
It works in all APIS
val vibration = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val vbManager =
getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
vbManager.defaultVibrator
} else {
#Suppress("DEPRECATION")
getSystemService(VIBRATOR_SERVICE) as Vibrator
}
if (vibration.hasVibrator()) {
vibration.vibrate(VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE))
}
As the title says, i upgraded to API 31. I had a function to perform a vibration, but in the line
val vib = this.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
the VIBRATOR_SERVICE is now shown as deprecated. How can i replace it? Or at least, what's the modern solution for API 31 and above?
EDIT: as Joachim Sauer wrote, the alternative is VibrationManager. What i need now is the equivalent line of code using VibrationManager.
val vib = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val vibratorManager =
getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
vibratorManager.defaultVibrator
} else {
#Suppress("DEPRECATION")
getSystemService(VIBRATOR_SERVICE) as Vibrator
}
The docs for this field say this:
This constant was deprecated in API level 31.
Use VibratorManager to retrieve the default system vibrator.
The most direct translation of code needing a Vibrator instance would be this:
val vibratorManager = this.getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
val vibrator = vibratorManager.getDefaultVibrator();
Generally speaking whenever a class/method/field is deprecated like this then you should first check the documentation. Almost every single time it will tell you what to use instead (or in some cases that it has no replacement).
This code works for both old and new android devices. Reference to the docs Vibrate constantly for the specified period of time.. You should use a VibrationEffect instead to create the vibration pattern.
In Java:
Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
final int DELAY = 0, VIBRATE = 1000, SLEEP = 1000, START = 0;
long[] vibratePattern = {DELAY, VIBRATE, SLEEP};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
vibrator.vibrate(VibrationEffect.createWaveform(vibratePattern, START));
} else {
// backward compatibility for Android API < 26
// noinspection deprecation
vibrator.vibrate(vibratePattern, START);
}
In Kotlin:
val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
val DELAY = 0
val VIBRATE = 1000
val SLEEP = 1000
val START = 0
val vibratePattern = longArrayOf(DELAY.toLong(), VIBRATE.toLong(), SLEEP.toLong())
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
vibrator.vibrate(VibrationEffect.createWaveform(vibratePattern, START))
} else {
// backward compatibility for Android API < 26
// noinspection deprecation
vibrator.vibrate(vibratePattern, START)
}
Edit
This method works for API level 30 below properly, so to completely use this on API level 31 above you need to use VIBRATOR_MANAGER_SERVICE instead of VIBRATOR_SERVICE, to retrieve the default vibrator service.
The correct code is below (in Java) :
Vibrator vibrator;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
VibratorManager vibratorManager = (VibratorManager) getSystemService(Context.VIBRATOR_MANAGER_SERVICE);
vibrator = vibratorManager.getDefaultVibrator();
} else {
// backward compatibility for Android API < 31,
// VibratorManager was only added on API level 31 release.
// noinspection deprecation
vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
}
final int DELAY = 0, VIBRATE = 1000, SLEEP = 1000, START = 0;
long[] vibratePattern = {DELAY, VIBRATE, SLEEP};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
vibrator.vibrate(VibrationEffect.createWaveform(vibratePattern, START));
} else {
// backward compatibility for Android API < 26
// noinspection deprecation
vibrator.vibrate(vibratePattern, START);
}
The correct code is below (in Kotlin) :
val vibrator: Vibrator
vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val vibratorManager: VibratorManager = getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
vibratorManager.getDefaultVibrator()
} else {
// backward compatibility for Android API < 31,
// VibratorManager was only added on API level 31 release.
// noinspection deprecation
getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
}
val DELAY = 0
val VIBRATE = 1000
val SLEEP = 1000
val START = 0
val vibratePattern = longArrayOf(DELAY.toLong(), VIBRATE.toLong(), SLEEP.toLong())
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
vibrator.vibrate(VibrationEffect.createWaveform(vibratePattern, START))
} else {
// backward compatibility for Android API < 26
// noinspection deprecation
vibrator.vibrate(vibratePattern, START)
}
Pulled together the various answers and cleaned them up to take into account changes in SDK 31 and 26, while providing backward compatibility.
#SuppressWarnings("deprecation")
private void vibrate() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
VibratorManager vibratorManager = (VibratorManager) getContext().getSystemService(Context.VIBRATOR_MANAGER_SERVICE);
Vibrator vibrator = vibratorManager.getDefaultVibrator();
vibrator.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE));
}
else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
Vibrator vibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE));
} else {
// API < 26
Vibrator vibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(500);
}
}
Handle SDK < 26, 26..32 and >= 33
private val vibrator: Vibrator by lazy {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
(getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager).defaultVibrator
} else {
#Suppress("DEPRECATION")
getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
}
}
#SuppressLint("MissingPermission")
private fun startVibrator() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
vibrator.vibrate(
VibrationEffect.createOneShot(1000, VibrationEffect.DEFAULT_AMPLITUDE),
VibrationAttributes.createForUsage(VibrationAttributes.USAGE_ALARM)
)
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
#Suppress("DEPRECATION")
vibrator.vibrate(
VibrationEffect.createOneShot(1000, VibrationEffect.DEFAULT_AMPLITUDE),
AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM)
.build()
)
} else {
#Suppress("DEPRECATION")
vibrator.vibrate(1000)
}
}
I created a wrapper class to handle the compatibility issue:
class VibratorHelper private constructor(private val context: Context) {
#Suppress("DEPRECATION")
fun vibrate(duration: Long) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val vibratorManager = context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
vibratorManager.defaultVibrator.run {
cancel()
vibrate(VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE))
}
} else {
val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vibrator.cancel()
if (Build.VERSION.SDK_INT >= 26) {
vibrator.vibrate(VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE))
} else {
vibrator.vibrate(duration)
}
}
}
companion object {
#JvmStatic
fun from(context: Context): VibratorHelper? {
val hasVibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val vibratorManager = context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
vibratorManager.defaultVibrator.hasVibrator()
} else {
#Suppress("DEPRECATION")
val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vibrator.hasVibrator()
}
return if (hasVibrator) VibratorHelper(context.applicationContext) else null
}
}
}
Here's how to use it:
val vibrator = VibratorHelper.from(context)
vibrator?.vibrate(500)
this is simple answer for both old and new api
Give permission for vibration
<uses-permission android:name="android.permission.VIBRATE" />
After that use this code for kotlin
#Suppress("DEPRECATION")
private fun vibrate(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val vibratorManager = getSystemService(VIBRATOR_MANAGER_SERVICE) as VibratorManager
vibratorManager.defaultVibrator
} else {
val vibrator = getSystemService(VIBRATOR_SERVICE) as Vibrator
vibrator.vibrate(10)
}
}
after that just call the method
This is what I use in my app (Kotlin). It handles all the old versions and hides the deprecated warnings. It does one short vibrate.
fun AppCompatActivity.vibrate() {
val vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val vibratorManager = getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
vibratorManager.defaultVibrator
} else {
#Suppress("DEPRECATION")
getSystemService(AppCompatActivity.VIBRATOR_SERVICE) as Vibrator
}
val duration = 200L
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
vibrator.vibrate(VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE))
} else {
#Suppress("DEPRECATION")
vibrator.vibrate(duration)
}
}
I thought I only have to insert <uses-permission android:name="android.permission.VIBRATE" /> to AndroidManifest.xml and a function with that content:
context?.getSystemService(Context.VIBRATOR_SERVICE).vibrate(30)
Reference
private fun Fragment.vibratePhone() {
val vibrator = context?.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
if (Build.VERSION.SDK_INT >= 26) {
vibrator.vibrate(VibrationEffect.createOneShot(200, VibrationEffect.DEFAULT_AMPLITUDE))
} else {
vibrator.vibrate(200)
}
}
I need it for API 22 and above.
I saw that we have telephonyManager.getServiceState - but I don't know how to get it for sim1 and for sim2 exactly.
Also we have CellInfo.serviceState - but it's only from API 28.
How to get it? I don't need any listeners, I just want to get service state at the certain time
Please help!
After some researches, implemented this solution:
#SuppressLint("MissingPermission", "NewApi")
private fun getServiceState(simSlotNmb: Int): String {
try {
val serviceState: ServiceState?
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
serviceState = if (subscriptionManager != null && subscriptionManager!!.activeSubscriptionInfoCount > 1) {
val subsId =
subscriptionManager!!.getActiveSubscriptionInfoForSimSlotIndex(
simSlotNmb
).subscriptionId
val telephonyManager =
(context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager)
.createForSubscriptionId(subsId)
telephonyManager.serviceState
} else {
telephonyManager.serviceState
}
} else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && subscriptionManager != null
&& subscriptionManager!!.activeSubscriptionInfoCount > 1) {
val subsId = subscriptionManager!!.getActiveSubscriptionInfoForSimSlotIndex(simSlotNmb).subscriptionId
val telephonyManagerForSlot
= (context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager)
.createForSubscriptionId(subsId)
telephonyManagerForSlot.listen(phoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE)
telephonyManagerForSlot.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE)
serviceState = latestServiceState
} else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1 && subscriptionManager != null
&& subscriptionManager!!.activeSubscriptionInfoCount > 1) {
val noConnectionDbm = -110
val dbm = getSignalDbm(simSlotNmb)
serviceState = ServiceState()
if(dbm < noConnectionDbm) {
serviceState.state = ServiceState.STATE_OUT_OF_SERVICE
} else {
serviceState.state = ServiceState.STATE_IN_SERVICE
}
} else {
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE)
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE)
serviceState = latestServiceState
}
return when (serviceState?.state) {
ServiceState.STATE_IN_SERVICE -> "in service"
ServiceState.STATE_EMERGENCY_ONLY -> "emergency only"
else -> "out of service"
}
} catch (exc: Exception) {
exc.printStackTrace()
return when(exc) {
is ArrayIndexOutOfBoundsException -> "out of service"
else -> Constants.error
}
}
}