【问题标题】:Android vibration app doesn't work anymore after Android 10, API 29 updateAndroid 10、API 29 更新后,Android 振动应用程序不再工作
【发布时间】:2020-06-13 10:35:52
【问题描述】:

所以几个月前我制作了一款帮助我改善睡眠的应用。我有睡眠问题,这听起来很奇怪,但是当我上床睡觉时,我会使用该应用程序振动手机,让自己专注于入睡,这目前是我睡眠程序的一个重要方面。

但是,我昨天将手机更新到了 Android 10,它完全破坏了应用程序。以前,当我单击开始按钮时应用程序会振动,即使在我使用后台服务、广播接收器和唤醒锁锁定手机后,应用程序也会继续振动。但是现在,在我锁定手机后应用程序停止振动,并且控制台中没有任何内容说明它为什么这样做。

如果有人可以就我可以在代码中更改什么或其他内容提供建议,我将不胜感激,因为我完全不知道该怎么做,我必须以某种方式让它工作。

代码如下:

MainActivity 中处理服务振动开始的函数:

// Event for when the VIBRATE button is pressed
public void beginVibration(View view) {
    // Given either of the bars are not 0
    if (durationBar.getProgress() != 0 || delayBar.getProgress() != 0) {
        // Get the values for each bar and set them accordingly in the vibration value array
        long[] pattern = {0, durationBar.getProgress(), delayBar.getProgress()};

        // Setup the ServiceConnection to monitor the Vibrate service
        c = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                m_service = ((Vibrate.MyBinder)service).getService();
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                m_service = null;
            }
        };

        // Bind the service to the connection
        bindService(i, c, BIND_AUTO_CREATE);

        // Insert the pattern into the intent itself
        i.putExtra("pattern", pattern);

        // Start the vibrate service
        this.startService(i);
    }
}

振动服务类:

public class Vibrate extends Service {

// Vibration object
private Vibrator v;

/*
THESE THREE ARE FOR PREVENTING THE VIBRATION FROM STOPPING AFTER THE PHONE IS PUT TO SLEEP
*/
// Wake Lock object
private PowerManager.WakeLock wl;

// Manager for the notifications
private NotificationManagerCompat m_notificationManager;

// BroadcastReceiver object
public BroadcastReceiver re;

public AudioAttributes audioAttributes;

// Not gonna lie, Idk what this does just know it is part of the binding process within MainActivity
public class MyBinder extends Binder {
    public Vibrate getService() {
        return Vibrate.this;
    }
}

@Override
public void onCreate() {
    super.onCreate();

    // Acquire the Wake Lock
    PowerManager pw = (PowerManager) getSystemService(POWER_SERVICE);
    wl = pw.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WL:");
    wl.acquire();

    // Get the vibration service
    v = (Vibrator) getSystemService(VIBRATOR_SERVICE);
    AudioAttributes audioAttributes = new AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
            .setUsage(AudioAttributes.USAGE_ALARM)
            .build();

}

@Override
public int onStartCommand(Intent i, int flags, int startId) {

    // Ensure that an intent with a long array has been passed
    if (i != null && i.getExtras() != null) {
        // Get the array
        final long[] pattern = i.getExtras().getLongArray("pattern");
        // Begin the vibration
        v.vibrate(pattern, 0);

        // Intialize the BroadcastReceiver and set it to trigger when the screen is turned off,
        // thus triggering the vibrations
        re = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
                    Log.i("VIZZY: ", "VIBRATION STARTED");
                    v.vibrate(pattern, 0, audioAttributes);
                    Log.i("VIZZY: ", "VIBRATION BEGUn");
                }
            }
        };

        // Add a listener for when the screen turns off and register the receiver
        IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
        registerReceiver(re, filter);
    }

    return Service.START_STICKY;
}

@Override
public void onDestroy() {
    // If the phone was put to sleep, cancel the notification keeping the vibration going
    if (m_notificationManager != null) {
        m_notificationManager.cancel(001);
    }

    // Release the Wake Lock, unregister the BroadcastReceiver, and stop the vibrations
    wl.release();
    unregisterReceiver(re);
    v.cancel();
}

@Override
public IBinder onBind(Intent intent) {
    return null;
}

private void addNotification() {
    // create the notification
    Notification.Builder m_notificationBuilder = new Notification.Builder(this)
    .setContentTitle("VIZZY")
    .setContentText("VIBRATING")
            .setSmallIcon(R.mipmap.ic_launcher);





    // create the pending intent and add to the notification
    Intent intent = new Intent(this, Vibrate.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
    m_notificationBuilder.setContentIntent(pendingIntent);

    m_notificationManager = NotificationManagerCompat.from(this);

    // send the notification
    m_notificationManager.notify(001, m_notificationBuilder.build());
}

}

提前感谢大家的帮助。

【问题讨论】:

    标签: android android-10.0 android-vibration


    【解决方案1】:

    我遇到了同样的问题。而且我发现从目标 29 开始,振动将在后台工作,只有将正确的音频属性传递给方法:

    public void vibrate(VibrationEffect vibe, AudioAttributes attributes);

    你可以尝试这样使用:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 
        vibrator.vibrate(VibrationEffect.createWaveform(pattern, 0), 
                new AudioAttributes.Builder()
                        .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                        .setUsage(AudioAttributes.USAGE_ALARM)
                        .build()); 
    } else { 
        vibrator.vibrate(pattern, 0);
    }
    

    【讨论】:

    • 这对我有用!我不喜欢 Android 框架给我们的反馈很差,只是默默地失败了。
    • 太好了,这个解决方案为我节省了很多时间来弄清楚为什么我的应用突然停止振动。
    【解决方案2】:

    它可能不关心这些指令:

    IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
    registerReceiver(re, filter);
    

    所以它可能应该是类似的:

    if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.Q){
        IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
        registerReceiver(re, filter);
    } else {
        /* whatever it takes to make it work >= API level 29 */
    }
    

    Intent.ACTION_SCREEN_ONIntent.ACTION_SCREEN_OFF 通常要求应用程序正在运行。但是 Android 10 behavior changes 没有提到类似的东西,因此很难说。此外,receiving broadcasts 也没有说明最近的变化。

    【讨论】:

    • 您好,感谢您的帮助!使用你所说的以及其他一些线程,我最终让它再次正常运行。我最终改变了发出通知的方式,并启动了两个前台服务来强制手机振动。我不确定这是否有意义,我什至不完全理解它是如何工作的。不过感谢您的帮助!
    • 它确实可以是发送方或接收方,当没有正确接收到意图时。使用两个服务(这看起来很奇怪),它最终可能还会注册两次唤醒锁和接收器。
    猜你喜欢
    • 2022-10-19
    • 1970-01-01
    • 2019-07-22
    • 2018-04-15
    • 2021-11-09
    • 2015-12-06
    • 2020-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多