中断车载收音机 android 蓝牙
Interrupt car radio android bluetooth
我们正在尝试通过蓝牙连接的汽车音响播放来自我们的 android 应用程序(交通信息)的音频警报。如果我们将汽车立体声音频输入切换为蓝牙,应用音频就会播放。如果它位于任何其他来源,则应用程序音频不会从立体声或设备播放。
我们想要做的是允许用户保持 DAB/FM 收音机或其他来源的立体声音频输入,但让我们的应用程序音频在特定时间中断并播放这些交通信息警报,例如VOIP
应用程序可以做到(例如 Facebook Messenger),内置电话 phone 通话应用程序可以做到。
这是我们目前使用的代码:
MainActivity.java
package com.robbresearch.ttsandroidtest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.content.Context;
import android.media.AudioManager;
public class MainActivity extends AppCompatActivity {
private Button speakNowButton;
private TextView textView;
TTSManager ttsManager = null;
AudioManager am;
AudioManager.OnAudioFocusChangeListener afChangeListener =
new AudioManager.OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
// Pause playback
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
// Resume playback
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
//am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
am.abandonAudioFocus(afChangeListener);
// Stop playback
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Context mContext = getApplicationContext();
ttsManager = new TTSManager();
ttsManager.init(this);
am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
// Use the music stream.
AudioManager.STREAM_VOICE_CALL,
// Request permanent focus.
AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
//am.registerMediaButtonEventReceiver(RemoteControlReceiver);
// Start playback.
}
am.setMode(AudioManager.MODE_IN_CALL);
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
textView = (TextView) findViewById(R.id.input_text);
speakNowButton = (Button) findViewById(R.id.speak_now);
speakNowButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
String text = textView.getText().toString();
ttsManager.initQueue(text);
}
});
}
/**
* Releases the resources used by the TextToSpeech engine.
*/
@Override
public void onDestroy() {
super.onDestroy();
ttsManager.shutDown();
}
}
activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="10dp"
android:orientation="vertical"
android:padding="20dp" >
<TextView
android:id="@+id/input_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:ems="10"
android:padding="10dp"
android:text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum." />
<Button
android:id="@+id/speak_now"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Speak Now" />
</LinearLayout>
我们在 android 清单中有这些额外的权限:
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
我们将不胜感激关于如何实现这一目标的任何建议,谢谢:)
我们只需要在必要时支持更新版本的 android。
要解决您的问题,我们必须首先了解汽车音响系统提供的蓝牙功能。
汽车音响系统支持 A2DP 配置文件和免提配置文件以实现通话。 Now, when bluetooth is selected as the source anything which is played by your app on A2DP profile will be played by audio system.但是,一旦您切换到其他来源(如收音机),即使您的设备已通过带有汽车音响系统的 A2DP 配置文件连接,也不会播放您现在所面对的任何内容。然而,这里可以尝试的一些事情也会中断广播播放:
- 我们知道,当有任何来电时,即使我们正在收听广播,我们也会通过 phone 号码收到提醒。您可以将此警报部分用于您的解决方案。但是,我不太清楚我们是否可以从应用程序发送 phone 振铃警报。这些警报处于较低级别,只是 AT 命令。需要一些搜索来检查这一点。
- 在某些汽车音响系统中,有一种功能可以在收到短信时提醒您。这个警报部分也可以探索。
我看到这两个选项可以帮助你。但这不是我猜的唯一选择。请尝试查找汽车音响系统蓝牙规格 sheet。在那里您可以了解他们提供的其他蓝牙警报功能。
我会更新这个答案,如果发现任何关于我上述建议的提示。
谢谢
我能够使用以下代码让它工作:
audioM.setMode(audioM.MODE_IN_COMMUNICATION);
audioM.setBluetoothScoOn(true);
audioM.startBluetoothSco();
audioM.setSpeakerphoneOn(false);
以及以下权限:
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
无需设置线程优先级或请求音频焦点。
请注意,我目前在调用 TextToSpeech.speak() 和通过汽车收音机收听音频之间有 15 秒的延迟。当我解决了这个问题后,我会更新这个答案。
我们正在尝试通过蓝牙连接的汽车音响播放来自我们的 android 应用程序(交通信息)的音频警报。如果我们将汽车立体声音频输入切换为蓝牙,应用音频就会播放。如果它位于任何其他来源,则应用程序音频不会从立体声或设备播放。
我们想要做的是允许用户保持 DAB/FM 收音机或其他来源的立体声音频输入,但让我们的应用程序音频在特定时间中断并播放这些交通信息警报,例如VOIP
应用程序可以做到(例如 Facebook Messenger),内置电话 phone 通话应用程序可以做到。
这是我们目前使用的代码:
MainActivity.java
package com.robbresearch.ttsandroidtest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.content.Context;
import android.media.AudioManager;
public class MainActivity extends AppCompatActivity {
private Button speakNowButton;
private TextView textView;
TTSManager ttsManager = null;
AudioManager am;
AudioManager.OnAudioFocusChangeListener afChangeListener =
new AudioManager.OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
// Pause playback
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
// Resume playback
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
//am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
am.abandonAudioFocus(afChangeListener);
// Stop playback
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Context mContext = getApplicationContext();
ttsManager = new TTSManager();
ttsManager.init(this);
am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
// Use the music stream.
AudioManager.STREAM_VOICE_CALL,
// Request permanent focus.
AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
//am.registerMediaButtonEventReceiver(RemoteControlReceiver);
// Start playback.
}
am.setMode(AudioManager.MODE_IN_CALL);
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
textView = (TextView) findViewById(R.id.input_text);
speakNowButton = (Button) findViewById(R.id.speak_now);
speakNowButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
String text = textView.getText().toString();
ttsManager.initQueue(text);
}
});
}
/**
* Releases the resources used by the TextToSpeech engine.
*/
@Override
public void onDestroy() {
super.onDestroy();
ttsManager.shutDown();
}
}
activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="10dp"
android:orientation="vertical"
android:padding="20dp" >
<TextView
android:id="@+id/input_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:ems="10"
android:padding="10dp"
android:text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum." />
<Button
android:id="@+id/speak_now"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Speak Now" />
</LinearLayout>
我们在 android 清单中有这些额外的权限:
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
我们将不胜感激关于如何实现这一目标的任何建议,谢谢:)
我们只需要在必要时支持更新版本的 android。
要解决您的问题,我们必须首先了解汽车音响系统提供的蓝牙功能。
汽车音响系统支持 A2DP 配置文件和免提配置文件以实现通话。 Now, when bluetooth is selected as the source anything which is played by your app on A2DP profile will be played by audio system.但是,一旦您切换到其他来源(如收音机),即使您的设备已通过带有汽车音响系统的 A2DP 配置文件连接,也不会播放您现在所面对的任何内容。然而,这里可以尝试的一些事情也会中断广播播放:
- 我们知道,当有任何来电时,即使我们正在收听广播,我们也会通过 phone 号码收到提醒。您可以将此警报部分用于您的解决方案。但是,我不太清楚我们是否可以从应用程序发送 phone 振铃警报。这些警报处于较低级别,只是 AT 命令。需要一些搜索来检查这一点。
- 在某些汽车音响系统中,有一种功能可以在收到短信时提醒您。这个警报部分也可以探索。
我看到这两个选项可以帮助你。但这不是我猜的唯一选择。请尝试查找汽车音响系统蓝牙规格 sheet。在那里您可以了解他们提供的其他蓝牙警报功能。
我会更新这个答案,如果发现任何关于我上述建议的提示。
谢谢
我能够使用以下代码让它工作:
audioM.setMode(audioM.MODE_IN_COMMUNICATION);
audioM.setBluetoothScoOn(true);
audioM.startBluetoothSco();
audioM.setSpeakerphoneOn(false);
以及以下权限:
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
无需设置线程优先级或请求音频焦点。
请注意,我目前在调用 TextToSpeech.speak() 和通过汽车收音机收听音频之间有 15 秒的延迟。当我解决了这个问题后,我会更新这个答案。