'VIBRATOR_SERVICE: String' is deprecated for API 31 - android

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)
}
}

Related

Android getParcelableExtra deprecated in api 33

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.

Vibration on button click not working in Android Studio

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))
}

Creating a vibrator for Android in Kotlin

I'm trying to add vibration effects to my Android game. I found some code that seems to work, but it's deprecated. What's the current way to create and deploy a vibrator?
var vibrator:Vibrator = getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
vibrator.vibrate(createPredefined(EFFECT_CLICK))
}else{
vibrator.vibrate(50)
}
The parts that are showing up as deprecated are "VIBRATOR-SERVICE" and vibrate.vibrate(50).
Step 1 : Add permission to the AndroidMenifest.xml
<uses-permission android:name="android.permission.VIBRATE" />
Step 2 : You can use this function for vibration.
if (ctx != null) {
if (Build.VERSION.SDK_INT >= 31) {
val vibratorManager =
ctx.getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
val vibrator = vibratorManager.defaultVibrator
vibrator.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK))
} else {
val v = ctx.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
if (Build.VERSION.SDK_INT >= 26) {
v.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK))
} else {
v.vibrate(200L)
}
}
}

How to open Settings panel in Android Q programmatically?

As per Android Q new features, there is a inline settings panel showing key connectivity settings that lets the user modify different connectivity settings such as airplane mode, wifi, volume, NFC and internet connectivity.
How can I open that settings panel programmatically from my app? like in screenshot below.
This is very simple and easy to implement using Settings panel API available in Android Q.
Simple we need to trigger intent with one of the new Settings.Panel actions.
To open Internet Connectivity Panel:
Java:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Intent panelIntent = new Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY)
startActivityForResult(panelIntent, 545)
}
Kotlin:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val panelIntent = Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY)
startActivityForResult(panelIntent, 545)
}
To open Volume control panel:
Java:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Intent panelIntent = new Intent(Settings.Panel.ACTION_VOLUME)
startActivityForResult(panelIntent, 545)
}
Kotlin:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val panelIntent = Intent(Settings.Panel.ACTION_VOLUME)
startActivityForResult(panelIntent, 545)
}
To open WIFI panel:
Java:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Intent panelIntent = new Intent(Settings.Panel.ACTION_WIFI)
startActivityForResult(panelIntent, 545)
}
Kotlin:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val panelIntent = Intent(Settings.Panel.ACTION_WIFI)
startActivityForResult(panelIntent, 545)
}
To open NFC panel:
Java:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Intent panelIntent = new Intent(Settings.Panel.ACTION_NFC)
startActivityForResult(panelIntent, 545)
}
Kotlin:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val panelIntent = Intent(Settings.Panel.ACTION_NFC)
startActivityForResult(panelIntent, 545)
}
Here you can check more about settings panel from Android official doc:
1) https://developer.android.com/preview/features#settings-panels
2) https://developer.android.com/reference/android/provider/Settings.Panel

Android Alarm Not Set

I used to set alarms using the following code-segment in other projects as repeating and non-repeating, but it's now driving me crazy about what may the silly mistake be that I've made for not the alarm speaking to my current implementation :\ :
private fun setAlarm(obj: MyObject, time: Long) {
val intent = Intent(applicationContext, MyAlarmIntentService::class.java)
intent.putExtra(C.KEY_ME, obj)
val pendingIntent = PendingIntent.getService(applicationContext, 43, intent,
PendingIntent.FLAG_UPDATE_CURRENT)
val context = this#MyActivity
val cal = Calendar.getInstance()
cal.timeInMillis = time * 1000 // time is in seconds
Log.d("setAlarm", "setting time -> $time for obj = $obj")
Log.d("setAlarm", "Set calendar: " + cal.toString())
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
#RequiresApi(Build.VERSION_CODES.LOLLIPOP) // Overriding doze-mode
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val alarmClockInfo =
AlarmManager.AlarmClockInfo(cal.timeInMillis, null)
alarmManager.setAlarmClock(alarmClockInfo, pendingIntent)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) // Overriding doze-mode
// Not-working in Nexus 6 - API 25 (7.1.1), but works in API 23 (6.0.1, tested in multiple devices)
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
cal.timeInMillis, pendingIntent)
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) // Works
alarmManager.setExact(AlarmManager.RTC_WAKEUP, cal.timeInMillis, pendingIntent)
else // works
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.timeInMillis, pendingIntent)
}
The IntentService class is as the following:
class MyAlarmIntentService : IntentService("Notification") {
override fun onHandleIntent(intent: Intent?) {
val obj = intent?.getParcelableExtra<MyObj>(C.KEY_ME) ?: return
Lg.d(TAG, "My alarm fired for - \n" + obj.toString())
}
companion object {
private val TAG = ContestAlarmIntentService::class.java.simpleName
}
}
The service is declared in manifest as:
<service android:name=".services.MyAlarmIntentService" />
The following is an example of the mentioned log inside setAlarm() method:
E/setAlarm: setting time -> 1514993850 for obj = MyObj{...}
E/setAlarm: Set calendar: java.util.GregorianCalendar[time=1514993850000,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=libcore.util.ZoneInfo[id="Asia/Dhaka",mRawOffset=21600000,mEarliestRawOffset=23400000,mUseDst=false,mDstSavings=0,transitions=7],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2018,MONTH=0,WEEK_OF_YEAR=1,WEEK_OF_MONTH=1,DAY_OF_MONTH=3,DAY_OF_YEAR=3,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=1,AM_PM=1,HOUR=9,HOUR_OF_DAY=21,MINUTE=37,SECOND=30,MILLISECOND=0,ZONE_OFFSET=21600000,DST_OFFSET=0]
This used to be a straight-forward code to me, but which fundamental may I be missing for these 3 days' of test sessions?
Sorry I did not go through all your code as I was busy in another task, so here's my code used with Broadcast
Intent intent = new Intent(context, AlarmReceiver.class);
intent.setAction(UtilAlarmConstants.ALARM_ACTION);
pIBroadCast = PendingIntent.getBroadcast(context, ALARM_PI_REQ_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager = (AlarmManager) context.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
if (alarmManager != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
alarmManager.setExactAndAllowWhileIdle(ALARM_TYPE, calendar.getTimeInMillis(),pendingIntent);
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AlarmManager.AlarmClockInfo alarmClockInfo
= new AlarmManager.AlarmClockInfo(System.currentTimeMillis() + fireAT, null);
alarmManager.setAlarmClock(alarmClockInfo, pIBroadCast);
}
//setExact for 19
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, fireAT, pIBroadCast);
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP, fireAT, pIBroadCast);
}
}
and Broadcast
if (intent != null && intent.getAction() != null) {
if (intent.getAction().equalsIgnoreCase(UtilAlarmConstants.ALARM_ACTION)) {
setUpNotification(context, intent);}
sorry for not giving answer related to service as they are all same wacky dacky :)

Categories

Resources