ssu*_*ukk 29
有可能的.使用下面的代码(FOR NEWER ANDROIDS,ESP.MARSHMALLOW,见答案的底部):
public class SettingsContentObserver extends ContentObserver {
    int previousVolume;
    Context context;
    public SettingsContentObserver(Context c, Handler handler) {
        super(handler);
        context=c;
        AudioManager audio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        previousVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC);
    }
    @Override
    public boolean deliverSelfNotifications() {
        return super.deliverSelfNotifications();
    }
    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        AudioManager audio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        int currentVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC);
        int delta=previousVolume-currentVolume;
        if(delta>0)
        {
            Logger.d("?ciszy?!"); // volume decreased.
            previousVolume=currentVolume;
        }
        else if(delta<0)
        {
            Logger.d("Zrobi? g?o?niej!"); // volume increased.
            previousVolume=currentVolume;
        }
    }
}
然后在您的服务onCreate注册它:
mSettingsContentObserver = new SettingsContentObserver(this,new Handler());
getApplicationContext().getContentResolver().registerContentObserver(android.provider.Settings.System.CONTENT_URI, true, mSettingsContentObserver );
然后在onDestroy中取消注册:
getApplicationContext().getContentResolver().unregisterContentObserver(mSettingsContentObserver);
请注意,此示例通过更改媒体音量来判断,如果要使用其他音量,请更改它!
更新:
上面的方法据说不适用于Marshmallow,但是自MediaSession推出以来,现在有更好的方法!首先,您必须将代码迁移到MediaController/MediaSession模式,然后使用以下代码:
private VolumeProviderCompat myVolumeProvider = null;
myVolumeProvider = new VolumeProviderCompat(VolumeProviderCompat.VOLUME_CONTROL_RELATIVE, maxVolume, currentVolume) {
    @Override
    public void onAdjustVolume(int direction) {
        // <0 volume down
        // >0 volume up
    }
};
mSession.setPlaybackToRemote(myVolumeProvider);
即使屏幕关闭,也会以某种方式检测音量按钮按下(如果适用于您的平台,请务必注册正确的媒体按钮意图接收器!)
更新2,因为GalDude要求获得有关获取媒体MediaSession/MediaController的更多信息.对不起,但是因为我停止使用Java,它将在Kotlin:
lateinit var mediaSession: MediaSessionCompat // you have to initialize it in your onCreate method
val kontroler: MediaControllerCompat
 get() = mediaSession.controller // in Java it's just getController() on mediaSession
// in your onCreate/start method:
mediaSession = MediaSessionCompat(this, "YourPlayerName", receiver, null)
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS or MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS)
mediaSession.isActive = true
if (ratingIsWorking) // note: rating crashes on some machines you have to check it!
    mediaSession.setRatingType(RatingCompat.RATING_5_STARS)
mediaSession.setCallback(object : MediaSessionCompat.Callback() {
...
// here you have to implement what happens with your player when play/pause/stop/ffw etc. is requested - see exaples elsewhere
})
// onDestroy/exit method:
mediaSession.isActive = false
mediaSession.release()
Joe*_*Joe 19
AOSP音乐应用程序有一个服务(MediaPlaybackService),它通过注册BroadcastReceiver(MediaButtonIntentReceiver)来响应音量键事件.
这是注册接收器的代码片段:
    mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    ComponentName rec = new ComponentName(getPackageName(),
            MediaButtonIntentReceiver.class.getName());
    mAudioManager.registerMediaButtonEventReceiver(rec);
另外,不要忘记清单:
    <receiver android:name="com.android.music.MediaButtonIntentReceiver">
        <intent-filter>
            <action android:name="android.intent.action.MEDIA_BUTTON" />
            <action android:name="android.media.AUDIO_BECOMING_NOISY" />
        </intent-filter>
    </receiver>
即使音乐应用程序不在前台,这也有效.这不是你想要的吗?
Ven*_*ryx 11
不幸的是,这是 Android 的另一个领域,其中有五种不同的方法可以“解决问题”,但大多数都不能很好地工作。为了我自己的理智,我将尝试在下面列出所有不同的方法。
MediaSession(来自服务)Denis Kniazhev 的回答:https ://stackoverflow.com/a/43304591/2441655
缺点:
1. 需要 Android SDK 21+ (Android 9+)。
android.media.VOLUME_CHANGED_ACTION(来自服务)Nikhil 的回答:https : //stackoverflow.com/a/44040282/2441655
缺点:
1. 不是 SDK 的官方部分:https : //stackoverflow.com/a/8974510/2441655
2. 忽略音量键的第一次按下(因为它只显示音量条)。
3. 100% 时忽略音量增大键,0% 时忽略音量减小键。
ContentObserver(来自服务)ssuukk 的回答:https ://stackoverflow.com/a/15292255/2441655 (第一部分)
缺点:
1. 在较新版本的 Android 中不起作用:dsemi 的评论
2. 忽略音量键的第一次按下(因为它只显示音量条)。
3. 100% 时忽略音量增大键,0% 时忽略音量减小键。
AudioManager.registerMediaButtonEventReceiver(来自服务)乔的回答:https : //stackoverflow.com/a/11510564/2441655
onKeyDown(来自活动)dipali 的回答:https ://stackoverflow.com/a/21086563/2441655
缺点:
1. 如果屏幕关闭,在不同的应用程序中等,则不起作用。
dispatchKeyEvent(来自活动)莫里斯·加文的回答:https : //stackoverflow.com/a/11462962/2441655
缺点:
1. 如果屏幕关闭,在不同的应用程序中等,则不起作用。
我目前使用的解决方案是#1,因为:
如果您发现任何其他人,或者您发现其中一些人的更多缺点,请告诉我!
我能够使用android 5+设备MediaSession.但是,ContentObserver@ssuukk建议在4.4和7.0设备上都不适合我(至少在我测试过的ROM上).这是一个适用于android 5+的完整示例.
服务:
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.v4.media.VolumeProviderCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
public class PlayerService extends Service {
    private MediaSessionCompat mediaSession;
    @Override
    public void onCreate() {
        super.onCreate();
        mediaSession = new MediaSessionCompat(this, "PlayerService");
        mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
                MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
        mediaSession.setPlaybackState(new PlaybackStateCompat.Builder()
                .setState(PlaybackStateCompat.STATE_PLAYING, 0, 0) //you simulate a player which plays something.
                .build());
        //this will only work on Lollipop and up, see https://code.google.com/p/android/issues/detail?id=224134
        VolumeProviderCompat myVolumeProvider =
                new VolumeProviderCompat(VolumeProviderCompat.VOLUME_CONTROL_RELATIVE, /*max volume*/100, /*initial volume level*/50) {
            @Override
            public void onAdjustVolume(int direction) {
                /*
                -1 -- volume down
                1 -- volume up
                0 -- volume button released
                 */
            }
        };
        mediaSession.setPlaybackToRemote(myVolumeProvider);
        mediaSession.setActive(true);
    }
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        mediaSession.release();
    }
}
在AndroidManifest.xml:
<application ...>
    ...
    <service android:name=".PlayerService"/>
</application>
在您的活动中:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    startService(new Intent(this, PlayerService.class));
}
有几点需要注意:
Settings->Applications,找到应用程序并强制停止它以获得音量按钮.您需要从服务中播放空白声音,然后才能收听音量变化。以下对我有用
private MediaPlayer mediaPlayer;
public MyService() {
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    ........
    mediaPlayer = MediaPlayer.create(this, R.raw.blank);
    mediaPlayer.setLooping(true);
    mediaPlayer.start();
    .......
    return START_STICKY;
}
@Override
public void onDestroy() {
    mediaPlayer.stop();
    mediaPlayer.release();
    super.onDestroy();
}
int volumePrev = 0;
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if ("android.media.VOLUME_CHANGED_ACTION".equals(intent.getAction())) {
            int volume = intent.getIntExtra("android.media.EXTRA_VOLUME_STREAM_VALUE",0);
            Log.i(TAG, "volume = " + volume);
            if (volumePrev  < volume) {
                Log.i(TAG, "You have pressed volume up button");
            } else {
                Log.i(TAG, "You have pressed volume down button");
            }
            volumePrev = volume;
        }
    }
};
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    .....
    IntentFilter filter = new IntentFilter();
    filter.addAction("android.media.VOLUME_CHANGED_ACTION");
    registerReceiver(broadcastReceiver, filter);
    ....
    return START_STICKY;
}
 @Override
public void onDestroy() {
    .....
    unregisterReceiver(broadcastReceiver);
    .....
    super.onDestroy();
}
| 归档时间: | 
 | 
| 查看次数: | 52106 次 | 
| 最近记录: |