停止&来电时启动音乐

发布于 2024-10-31 13:12:42 字数 323 浏览 5 评论 0原文

我已经实现了一个从 Android 中的 URL 播放媒体的活动。

为了在来电时添加暂停功能,我创建了一个接收器,在来电时设置一个变量。 Activity 在 onPause() 中读取此变量,暂停音乐并重置它。当调用完成并且 Activity 恢复时,音乐将在 onResume() 中恢复。

只要活动有焦点,这种方法就可以正常工作。如果我在播放音乐时返回主屏幕,然后来电,则不会调用 onPause() 。因此,我无法停止和开始音乐。

有没有人实现了可以拦截来电/去电并正确停止/开始音乐的媒体播放器?

I have implemented an activity that plays media from a URL in Android.

In order to add pause functionality when a call is incoming I created a receiver that sets a variable when the call is coming. The activity reads this variable in onPause(), pauses the music and resets it. When the call is done and the activity is resumed, the music is resumed in onResume().

This works fine as long the activity has the focus. If I go back to home screen while the music is playing, and then the call comes, onPause() is not called. Hence, I can't stop and start the music.

Has anybody implemented a media player that intercepts incoming/outgoing calls and stops/starts music correctly?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

巷雨优美回忆 2024-11-07 13:12:42

您可以执行以下操作:

首先,您可以使用 PhoneStateListener 侦听通话状态的变化。
您可以在 TelephonyManager 中注册侦听器:

PhoneStateListener phoneStateListener = new PhoneStateListener() {
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        if (state == TelephonyManager.CALL_STATE_RINGING) {
            //Incoming call: Pause music
        } else if(state == TelephonyManager.CALL_STATE_IDLE) {
            //Not in call: Play music
        } else if(state == TelephonyManager.CALL_STATE_OFFHOOK) {
            //A call is dialing, active or on hold
        }
        super.onCallStateChanged(state, incomingNumber);
    }
};
TelephonyManager mgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
if(mgr != null) {
    mgr.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}

当不再需要侦听器时,请记住使用 PhoneStateListener.LISTEN_NONE 取消注册侦听器:

TelephonyManager mgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
if(mgr != null) {
    mgr.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
}

有关详细信息,请阅读文档

您可以做的另一件事是监听广播android.intent.action.PHONE_STATE。它将包含额外的 TelephonyManager.EXTRA_STATE,它将为您提供有关呼叫的信息。 查看此处的文档

请注意,在这两种情况下,您都需要 android.permission.READ_PHONE_STATE 权限。

There are a few things you can do:

First of all, you can listen for changes in the call state using a PhoneStateListener.
You can register the listener in the TelephonyManager:

PhoneStateListener phoneStateListener = new PhoneStateListener() {
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        if (state == TelephonyManager.CALL_STATE_RINGING) {
            //Incoming call: Pause music
        } else if(state == TelephonyManager.CALL_STATE_IDLE) {
            //Not in call: Play music
        } else if(state == TelephonyManager.CALL_STATE_OFFHOOK) {
            //A call is dialing, active or on hold
        }
        super.onCallStateChanged(state, incomingNumber);
    }
};
TelephonyManager mgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
if(mgr != null) {
    mgr.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}

Remember to unregister the listener when it's no longer needed using the PhoneStateListener.LISTEN_NONE:

TelephonyManager mgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
if(mgr != null) {
    mgr.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
}

For more information read the documentation.

Another thing you can do is listening for the broadcast android.intent.action.PHONE_STATE. It will contain the extra TelephonyManager.EXTRA_STATE which will give you information about the call. Take a look at the documentation here.

Please note that you'll need the android.permission.READ_PHONE_STATE-permission in both cases.

娇女薄笑 2024-11-07 13:12:42

我认为 AudioManager 是最好、最快的解决方案。这是我的实现示例:

public class MyActivity extends Activity implements OnAudioFocusChangeListener {

private AudioManager mAudioManager;

@Override
public void onCreate(Bundle savedInstanceState) {
    mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    mAudioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
}

@Override
 public void onDestroy(){
     super.onDestroy();
     ...
     mAudioManager.abandonAudioFocus(this);
     ...
 }

@Override
public void onAudioFocusChange(int focusChange) {
    if(focusChange<=0) {
        //LOSS -> PAUSE
    } else {
        //GAIN -> PLAY
       }
   }    
}

希望对您有帮助:-)

I think that AudioManager is the best and fast solution. Here there is my implementation example:

public class MyActivity extends Activity implements OnAudioFocusChangeListener {

private AudioManager mAudioManager;

@Override
public void onCreate(Bundle savedInstanceState) {
    mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    mAudioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
}

@Override
 public void onDestroy(){
     super.onDestroy();
     ...
     mAudioManager.abandonAudioFocus(this);
     ...
 }

@Override
public void onAudioFocusChange(int focusChange) {
    if(focusChange<=0) {
        //LOSS -> PAUSE
    } else {
        //GAIN -> PLAY
       }
   }    
}

I hope it's helpful for you :-)

掐死时间 2024-11-07 13:12:42

我认为 requestAudioFocus() 应该能够自动处理这种情况。您不需要显式检查呼叫状态。

Audio Focus 本质上是合作性的。也就是说,应用程序应该(并且强烈鼓励)遵守音频焦点指南,但系统并不强制执行这些规则。如果应用程序想要在失去音频焦点后播放响亮的音乐,系统中的任何内容都不会阻止这种情况。然而,用户更有可能获得不好的体验,并且更有可能卸载行为不当的应用程序。

要请求音频焦点,您必须从 AudioManager 调用 requestAudioFocus(),如下例所示:

AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);

if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    // could not get audio focus.
}

I think requestAudioFocus() should be able to handle this case automatically. You don't need to check call state explicitly.

Audio Focus is cooperative in nature. That is, applications are expected (and highly encouraged) to comply with the audio focus guidelines, but the rules are not enforced by the system. If an application wants to play loud music even after losing audio focus, nothing in the system will prevent that. However, the user is more likely to have a bad experience and will be more likely to uninstall the misbehaving application.

To request audio focus, you must call requestAudioFocus() from the AudioManager, as the example below demonstrates:

AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);

if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    // could not get audio focus.
}
漆黑的白昼 2024-11-07 13:12:42

您可以尝试广播接收器。

创建一个继承 BroadcastReceiverCallReceiver 类。

package com.example.callreceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;

public class CallReceiver extends BroadcastReceiver{
    TelephonyManager telManager;
    Context context;

@Override
public void onReceive(Context context, Intent intent) {


    this.context=context;

    telManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
    telManager.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);

}

private final PhoneStateListener phoneListener = new PhoneStateListener() {
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        try {
            switch (state) {
            case TelephonyManager.CALL_STATE_RINGING: {
                //PAUSE
            break;
            }
            case TelephonyManager.CALL_STATE_OFFHOOK: {

            break;
            }
            case TelephonyManager.CALL_STATE_IDLE: {
                //PLAY
            break;
            }
            default: { }
            }
            } catch (Exception ex) {

            }
        }
    };
 }

然后在 ma​​nifest.xml 文件中添加此行以将其注册到应用程序上

<receiver android:name="CallReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.PHONE_STATE" >
            </action>
        </intent-filter>
    </receiver>

You can try a broadcast receiver.

Create a class CallReceiver which extends BroadcastReceiver.

package com.example.callreceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;

public class CallReceiver extends BroadcastReceiver{
    TelephonyManager telManager;
    Context context;

@Override
public void onReceive(Context context, Intent intent) {


    this.context=context;

    telManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
    telManager.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);

}

private final PhoneStateListener phoneListener = new PhoneStateListener() {
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        try {
            switch (state) {
            case TelephonyManager.CALL_STATE_RINGING: {
                //PAUSE
            break;
            }
            case TelephonyManager.CALL_STATE_OFFHOOK: {

            break;
            }
            case TelephonyManager.CALL_STATE_IDLE: {
                //PLAY
            break;
            }
            default: { }
            }
            } catch (Exception ex) {

            }
        }
    };
 }

Then Add this line in manifest.xml file to register it on the App

<receiver android:name="CallReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.PHONE_STATE" >
            </action>
        </intent-filter>
    </receiver>
云雾 2024-11-07 13:12:42

对我来说,空闲状态是在有来电时出现的,快速解决方法是检查广播接收器

BroadcastReceiver phonestatereceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    Bundle extras = intent.getExtras();
    if (extras != null) {
      String state = extras.getString(TelephonyManager.EXTRA_STATE);
      if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
        //pause here
      }
      else if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
        //pause here
      }
      else if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
        //play here
      }
    }
  }
};

For me idle state was coming while there was incoming call, the quick fix is to check in the broadcast receiver

BroadcastReceiver phonestatereceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    Bundle extras = intent.getExtras();
    if (extras != null) {
      String state = extras.getString(TelephonyManager.EXTRA_STATE);
      if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
        //pause here
      }
      else if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
        //pause here
      }
      else if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
        //play here
      }
    }
  }
};
夜雨飘雪 2024-11-07 13:12:42

基于 mickesource 更新为 android Oreo+ 和 kotlin 。我在服务中添加了,您可以按照相同的活动或片段进行操作。

class MusicService : Service(), AudioManager.OnAudioFocusChangeListener {

var audioManager: AudioManager? = null
var audioFocusRequest:AudioFocusRequest?=null


override fun onCreate() {
    super.onCreate()    
    setAudioFocusChangeListener()
}


private fun setAudioFocusChangeListener() {

    audioManager = getSystemService(AUDIO_SERVICE) as AudioManager?

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        audioFocusRequest=AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
            .setAudioAttributes(
                AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_MEDIA)
                    .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                    .build()
            )
            .setAcceptsDelayedFocusGain(true)
            .setOnAudioFocusChangeListener(this).build()
        audioManager?.requestAudioFocus(audioFocusRequest!!)
    } else {
        @Suppress("deprecation")
        audioManager?.requestAudioFocus(
            this,
            AudioManager.STREAM_MUSIC,
            AudioManager.AUDIOFOCUS_GAIN
        )
    }
}

override fun onAudioFocusChange(focusChange: Int) {
    if(focusChange<=0){
        //Pause audio
    }else{
        //Play audio
    }
}

 

在 Android 10 上测试了常规调用和应用程序调用

Based on mickesource Updated for android Oreo+ and kotlin . I added in service , you can follow same for activity or fragment .

class MusicService : Service(), AudioManager.OnAudioFocusChangeListener {

var audioManager: AudioManager? = null
var audioFocusRequest:AudioFocusRequest?=null


override fun onCreate() {
    super.onCreate()    
    setAudioFocusChangeListener()
}


private fun setAudioFocusChangeListener() {

    audioManager = getSystemService(AUDIO_SERVICE) as AudioManager?

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        audioFocusRequest=AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
            .setAudioAttributes(
                AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_MEDIA)
                    .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                    .build()
            )
            .setAcceptsDelayedFocusGain(true)
            .setOnAudioFocusChangeListener(this).build()
        audioManager?.requestAudioFocus(audioFocusRequest!!)
    } else {
        @Suppress("deprecation")
        audioManager?.requestAudioFocus(
            this,
            AudioManager.STREAM_MUSIC,
            AudioManager.AUDIOFOCUS_GAIN
        )
    }
}

override fun onAudioFocusChange(focusChange: Int) {
    if(focusChange<=0){
        //Pause audio
    }else{
        //Play audio
    }
}

 

Tested on Android 10 for regular and what's app call

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文