I am using the following code to open the Equalizer in the App.
Intent intent = new Intent( );
intent.setAction("android.media.action.DISPLAY_AUDIO_EFFECT_CONTROL_PANEL");
if (intent.resolveActivity( getActivity().getPackageManager()) != null )
{
startActivityForResult( intent , 100 );
}
else
{
JBUtils.getInstance().showCustomToast( getActivity() , R.string.equalizer_notfound);
}
And added the permission
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
After user changes the Equalizer settings how to apply equalizer settings in the currently playing audio file.We are using the Exoplayer for playing the music file.
Thanks in Advance.
Please look at this issue (closed):
https://github.com/google/ExoPlayer/issues/252
There's an interesting example about using Equalizer in ExoPlayer.
I didn't try it yet but it seems an interesting starting point to integrate standard Equalizer in ExoPlayer.
Let me know if it works!
Here is the example I would start with:
audioRenderer = new MediaCodecAudioTrackRenderer(......){
private Equalizer equalizer;
#Override
public void onAudioSessionId ( int audioSessionId){
releaseEqualizer();
equalizer = new Equalizer(...,audioSessionId);
// Configure equalizer here.
equalizer.setEnabled(true);
}
#Override
public void onDisabled () {
releaseEqualizer();
}
private void releaseEqualizer () {
if (equalizer != null) {
equalizer.release();
equalizer = null;
}
}
};
Moreover there seems to be some issue with the equalizer. You can try to enable the workaround (disabled by default) in AudioTrack, setting the following flag to true:
public static boolean enablePreV21AudioSessionWorkaround = false;
You have to provide the your package name and current Media Player audio session id as extra before starting the activity. Add the below code before calling startActivityForResult.
intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, getPackageName());
intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, player.getAudioSessionId());
where player is an instance of MediaPlayer.
Related
I have an application that occasionally speaks via the systems text to speech(TTS) system, but if there's a background service (like an audiobook, or music stream) running at the same time they overlap.
I would like to pause the media, play my TTS, then unpause the media. I've looked, but can't find any solutions.
I believe if I were to play actual audio from my app, it would pause the media until my playback was complete (if I understand what I've found correctly). But TTS doesn't seem to have the same affect. The speech is totally dynamic, so I can't just record all the options.
Using the latest Xamarin.Forms, I've looked into all the media nuget packages I could find, and they all seem pretty centered on controlling media from files.
My only potential thought (I don't like it), is to maybe play an empty audio file while the TTS is running. But would like a more elegant solution if it exists.
(I don't care about iOS at the moment, so if it's an android only solution, I'm okay with it. And if it's native (java/kotlin), I can convert/incorporate it.)
Agree with rbonestell said, you can use DependencyService and AudioFocus to achieve it, when you record the audio, you can create interface in PCL.
public interface IControl
{
void StopBackgroundMusic();
}
When you record the audio, you can executed the DependencyService with following code.
private void Button_Clicked(object sender, EventArgs e)
{
DependencyService.Get<IControl>().StopBackgroundMusic();
//record the audio
}
In android folder, you can create a StopMusicService to achieve that.
[assembly: Dependency(typeof(StopMusicService))]
namespace TTSDemo.Droid
{
public class StopMusicService : IControl
{
AudioManager audioMan;
AudioManager.IOnAudioFocusChangeListener listener;
public void StopBackgroundMusic()
{
audioMan = (AudioManager)Android.App.Application.Context.GetSystemService(Context.AudioService);
listener = new MyAudioListener(this);
var ret = audioMan.RequestAudioFocus(listener, Stream.Music, AudioFocus.Gain);
}
}
internal class MyAudioListener :Java.Lang.Object, AudioManager.IOnAudioFocusChangeListener
{
private StopMusicService stopMusicService;
public MyAudioListener(StopMusicService stopMusicService)
{
this.stopMusicService = stopMusicService;
}
public void OnAudioFocusChange([GeneratedEnum] AudioFocus focusChange)
{
// throw new NotImplementedException();
}
}
}
Thanks to Leon Lu - MSFT, I was able to go in the right direction. I took his implementation (which has some deprecated calls to the Android API), and updated it for what I needed.
I'll be doing a little more work making sure it's stable and functional. I'll also see if I can clean it up a little too. But here's what works on my first test:
[assembly: Dependency(typeof(MediaService))]
namespace ...Droid.Services
{
public class MediaService : IMediaService
public async Task PauseBackgroundMusicForTask(Func<Task> onFocusGranted)
{
var manager = (AudioManager)Android.App.Application.Context.GetSystemService(Context.AudioService);
var builder = new AudioFocusRequestClass.Builder(AudioFocus.GainTransientMayDuck);
var focusRequest = builder.Build();
var ret = manager.RequestAudioFocus(focusRequest);
if (ret == AudioFocusRequest.Granted)
{
await onFocusGranted?.Invoke();
manager.AbandonAudioFocusRequest(focusRequest);
}
}
}
}
I am accessing the audio files from
/data/user/0/app_packagename/files/filename
I don't have WRITE_EXTERNAL READ_EXTERNAL permissions.
Now I can access files which are saved in the /data/user/0/app_packagename/files/ without WRITE_EXTERNAL READ_EXTERNAL permissions.
And can able to play all the audio files in my application.
In my application I am playing all files in queue. Few of my users are not able to play second audio file once 1st audio file completed.
Below is my code
void playNext(File varientFile) {
if (mSessionMediaPlayer != null) {
if (mSessionMediaPlayer.isPlaying()) {
mSessionMediaPlayer.stop();
}
mSessionMediaPlayer.release();
mSessionMediaPlayer = null;
}
mSessionMediaPlayer = new MediaPlayer();
if (mSessionMediaPlayer != null) {
Uri uri = Uri.parse(variantFile.getAbsolutePath());
mSessionMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mSessionMediaPlayer.setDataSource(this, uri);
mSessionMediaPlayer.setLooping(false);
mSessionMediaPlayer.prepare();
mSessionMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
playNext(mFiles.get(mNextIndex);
}
});
mSessionMediaPlayer.start();
runScheduler();
}
}
Instead of
mSessionMediaPlayer = new MediaPlayer();
I had tried with
mSessionMediaPlayer = MediaPlayer.create(getApplicationContext(),
uri);
Even MediaPlayer.create() is returning null. mSessionMediaPlayer.prepare() is throwing an exception
Cause : Prepare failed.: status=0x1
Whats wrong with my code? Why it is getting null or prepare failed? I had tested the files as well they are working, audio file format is in .aac.
The same user who is not able to play second audio file. He is able to play first file with the same code. But if same method is calling from onCompleted() it is not working. Why so?
Can anyone please help me to fix this issue?
Instead of creating a new object every time, try with the same Media Player object something like this.
MediaPlayer mSessionMediaPlayer;
mSessionMediaPlayer = MediaPlayer.create(getApplicationContext(),uri);
mSessionMediaPlayer.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mSessionMediaPlayer) {
moveToNext(mSessionMediaPlayer,nextUri);
}
});
mSessionMediaPlayer.prepare();
mSessionMediaPlayer.start();
private void moveToNext(MediaPlayer mSessionMediaPlayer,Uri uri){
mSessionMediaPlayer.create(getApplicationContext(), uri);
mSessionMediaPlayer.prepare();
mSessionMediaPlayer.start();
}
Trying to cast media to default media receiver of the Chromecast from android app, but it doesn't cast at all. Following is the code snippet using to find the routes :
MediaRouteSelector selector = new MediaRouteSelector.Builder()
.addControlCategory(CastMediaControlIntent
.categoryForRemotePlayback(CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID))
.build();
Then, it will show the Chromecast device within the WiFi and running the following code when the device is selected :
MediaRouter.RouteInfo route = adapter.getItem(position).routeInfo;
// select the route for usage
route.select();
// send the play control request with the video uri
route.sendControlRequest(
new Intent(MediaControlIntent.ACTION_PLAY)
.setDataAndType(videoUri, "video/mp4")
.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK),
new MediaRouter.ControlRequestCallback() {
#Override
public void onError(String error, Bundle data) {
super.onError(error, data);
}
#Override
public void onResult(Bundle data) {
super.onResult(data);
}
}
);
It can't cast the media to the device. Any suggestions ?
It seems like you are not using the Cast SDK but using the Media Route Provider. I don't see any session being set up; you might want to look at the democastplayer sample code that is distributed along with the Android SDK (under SDK folder, go to extras/google/google_play_service/samples/cast/democastplayer). In that sample, look at the MrpCastPlayerActivity class.
I am trying to autoplay youtube videos on android, which evry time i play video must press play button to play and that is a bad experince for the user, so i try many method but it dosnt work
so please guys help me ,thanks for advise
and this is a pieace of my code
#Override
public void onClick(View v) {
Intent intent = null;
intent=YouTubeStandalonePlayer.createVideoIntent(activity,DeveloperKey.DEVELOPER_KEY, VIDEO_ID);
activity.startActivity(intent);
}
autoplay = true;
lightboxMode = false;
intent = YouTubeStandalonePlayer.createVideoIntent(
this, YOUR_DEVELOPER_KEY, VIDEO_ID, startTimeMillis, autoplay, lightboxMode);
This works for me and can be found in youtube samples.
Documentation:
createVideoIntent(Activity activity, String developerKey, String videoId, int timeMillis, boolean autoplay, boolean lightboxMode)
Implementation example:
intent = YouTubeStandalonePlayer.createVideoIntent(this, DeveloperKey.DEVELOPER_KEY, VIDEO_ID, 0, true, false);
You need to pass true for autoplay parameter
How can you read data, i.e. convert simple text strings to voice (speech) in Android?
Is there an API where I can do something like this:
TextToVoice speaker = new TextToVoice();
speaker.Speak("Hello World");
Using the TTS is a little bit more complicated than you expect, but it's easy to write a wrapper that gives you the API you desire.
There are a number of issues you must overcome to get it work nicely.
They are:
Always set the UtteranceId (or else
OnUtteranceCompleted will not be
called)
setting OnUtteranceCompleted
listener (only after the speech
system is properly initialized)
public class TextSpeakerDemo implements OnInitListener
{
private TextToSpeech tts;
private Activity activity;
private static HashMap DUMMY_PARAMS = new HashMap();
static
{
DUMMY_PARAMS.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "theUtId");
}
private ReentrantLock waitForInitLock = new ReentrantLock();
public TextSpeakerDemo(Activity parentActivity)
{
activity = parentActivity;
tts = new TextToSpeech(activity, this);
//don't do speak until initing
waitForInitLock.lock();
}
public void onInit(int version)
{ //unlock it so that speech will happen
waitForInitLock.unlock();
}
public void say(WhatToSay say)
{
say(say.toString());
}
public void say(String say)
{
tts.speak(say, TextToSpeech.QUEUE_FLUSH, null);
}
public void say(String say, OnUtteranceCompletedListener whenTextDone)
{
if (waitForInitLock.isLocked())
{
try
{
waitForInitLock.tryLock(180, TimeUnit.SECONDS);
}
catch (InterruptedException e)
{
Log.e("speaker", "interruped");
}
//unlock it here so that it is never locked again
waitForInitLock.unlock();
}
int result = tts.setOnUtteranceCompletedListener(whenTextDone);
if (result == TextToSpeech.ERROR)
{
Log.e("speaker", "failed to add utterance listener");
}
//note: here pass in the dummy params so onUtteranceCompleted gets called
tts.speak(say, TextToSpeech.QUEUE_FLUSH, DUMMY_PARAMS);
}
/**
* make sure to call this at the end
*/
public void done()
{
tts.shutdown();
}
}
Here you go . A tutorial on using the library The big downside is that it requires an SD card to store the voices.
A good working example of tts usage can be found in the "Pro Android 2 book". Have a look at their source code for chapter 15.
There are third-party text-to-speech engines. Rumor has it that Donut contains a text-to-speech engine, suggesting it will be available in future versions of Android. Beyond that, though, there is nothing built into Android for text-to-speech.
Donut has this: see the android.speech.tts package.