Stream and Play .m4a stream (Itunes preview Url) in android - android

I want to stream and play itunes preview urls like http://a2.mzstatic.com/us/r1000/044/Music/e9/40/ec/mzm.evyxvimp.aac.p.m4a. I tried to use AAC Decoder Android Library. By which I can stream and play AAC stream urls like http://http.yourmuze.com:8000/play/paradise/l.aac. But it dnt stream m4a urls(Logcat says java.io.FileNotFoundException: http://a2.mzstatic.com/us/r1000/044/Music/e9/40/ec/mzm.evyxvimp.aac.p.m4a).
How I can stream the .m4a links?
My Code:
public class AACPlayerActivity extends Activity implements OnClickListener,PlayerCallback{
private Button btnPlay;
private ProgressBar progress;
private Handler uiHandler;
private MultiPlayer multiPlayer;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnPlay = (Button)findViewById(R.id.playButton);
progress = (ProgressBar)findViewById(R.id.progress);
progress.setVisibility(View.INVISIBLE);
btnPlay.setOnClickListener(this);
uiHandler = new Handler();
}
public void playerException(Throwable arg0) {
// TODO Auto-generated method stub
}
public void playerMetadata(String arg0, String arg1) {
// TODO Auto-generated method stub
}
public void playerPCMFeedBuffer(boolean arg0, final int audioBufferSizeMs, final int audioBufferCapacityMs) {
// TODO Auto-generated method stub
uiHandler.post(new Runnable() {
public void run() {
// TODO Auto-generated method stub
progress.setProgress( audioBufferSizeMs * progress.getMax() / audioBufferCapacityMs );
}
});
}
public void playerStarted() {
uiHandler.post(new Runnable() {
public void run() {
// TODO Auto-generated method stub
progress.setProgress( 0 );
progress.setVisibility( View.VISIBLE );
}
});
}
public void playerStopped(int arg0) {
// TODO Auto-generated method stub
uiHandler.post(new Runnable() {
public void run() {
// TODO Auto-generated method stub
progress.setVisibility( View.INVISIBLE );
}
});
}
public void onClick(View v) {
// TODO Auto-generated method stub
if(btnPlay.getText().equals("Play")){
start();
btnPlay.setText("stop");
}else{
stop();
}
}
private void start() {
stop();
// we cannot do it in playerStarted() - it is too late:
multiPlayer = new MultiPlayer(this,MultiPlayer.DEFAULT_AUDIO_BUFFER_CAPACITY_MS, MultiPlayer.DEFAULT_DECODE_BUFFER_CAPACITY_MS);
multiPlayer.playAsync("http://a2.mzstatic.com/us/r1000/044/Music/e9/40/ec/mzm.evyxvimp.aac.p.m4a");
}
private void stop() {
if (multiPlayer != null) {
multiPlayer.stop();
multiPlayer = null;
}
}
Updates
I try to use ServeStream it says the url could not be opened.
I try to use Vitamio SDK it also fails to play the itunes preview Urls.
Is possible to play itunes preview urls in android?

Take a look at ServeStream:
HTTP media server browser and stream player for Android.
Features:
Supports Android 2.2+, 3.0+ (No support for < 2.2)
Plays Android supported media files
Additional support for m3u, m3u8, pls and asx playlists
Supports multitasking/playing audio in the background
Repeat and shuffle modes
Alarm clock support
Home screen widget
Utilizes HTML parsing to allow navigation of HTTP media servers that serve HTML pages

M4A and AAC are supported by Android. I would recommend to read this page: http://developer.android.com/guide/appendix/media-formats.html
Just couple of thing which you should be aware of
a) Older devices may have no particular coded or format support (especially, if you go below OS 2.2)
b) Some cheap devices may have quite strange things integrated in audio/video stack. I saw it on couple of cheap Chinese devices.
So, you can try to use MediaPlayer API to play it:
http://developer.android.com/reference/android/media/MediaPlayer.html
You can take a look at example here:
http://blog.endpoint.com/2011/03/api-gaps-android-mediaplayer-example.html

It has nothing to do with media formats etc. Apple simply prevents non-Apple clients to access previews. You can spoof User-Agent header and access to previews.
Read my relevant blog post here: http://ahmetalpbalkan.com/blog/how-to-bypass-itunes-music-previews-protection/ Thats why you get 404 while playing music on Android. this should answer your question.

Related

How to trigger Vibration on Sound Input?

I am trying to create an android application where I filter one specific frequency of a beep and make the phone vibrate.
I am taking input from the MIC of mobile and using MediaRecorder class, by using this class, I can record, save and play the input. Now I need my mobile to vibrate whenever there is a beep/or any sound.
The input is given by a wire to the Headphone jack of the mobile so I know that there is only one frequency being input.
I have a button, Clicking which starts recording.
I have Permissions to vibrate and record in my manifest file already.
record.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
isRecording=true;
myAudioRecorder.prepare();
myAudioRecorder.start();
...
}
I also tried to search the internet and found kind of the similar question here but I am unable to find any correct answer.
However, I can make the phone vibrate on clicking another button and here is the snipt of code,
Vibrator vibrate;
vibrate = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
Btn1.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v) {
vibrate.vibrate(800);
}
}
I tried calling a Vibrator inside recorder.start(); function but this makes the phone vibrate even when there is no sound anymore.
I also tried getting help from this question so whenever there is silence, the phone should not vibrate, but I am getting confused, I somehow understand that there should be a Boolean which gets true when there is sound and make the phone vibrate, but I am unable to put this logic into code.
Please let me know what can I do in this context and which direction should I be searching in?
UPDATE
I found this toturial for showing the progress bar with amplitude of input sound, it works fine and I tried to make the phone vibrate when there is some value in buffer, Now it vibrates even when the amplitude is zero, I guess thats because of the fact that every vibration makes noise which leads the phone to vibrate. I am unable to check the function via TOAST because of java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare(). Is there any suggestion?
For your main problem, maybe you can check for the amplitude of the sound, and only vibrate if a minimum threshold has been reached. Something like this:
private class DetectAmplitude extends AsyncTask<Void, Void, Void> {
private MediaRecorder mRecorder = null;
private final static int MAX_AMPLITUDE = 32768;
//TODO: Investigate what is the ideal value for this parameter
private final static int MINIMUM_REQUIRED_AVERAGE = 5000;
#Override
protected Void doInBackground(Void... params) {
Boolean soundStarted = true;
if (mRecorder == null) {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mRecorder.setOutputFile("/dev/null");
try {
mRecorder.prepare();
} catch (IllegalStateException e) {
soundStarted = false;
Log.e(TAG, "Could not detect background noise. Error preparing recorder: " + e.getMessage());
} catch (IOException e) {
soundStarted = false;
Log.e(TAG, "Could not detect background noise. Error preparing recorder: " + e.getMessage());
}
try {
mRecorder.start();
} catch (RuntimeException e) {
Log.e(TAG, "Could not detect background noise. Error starting recorder: " + e.getMessage());
soundStarted = false;
mRecorder.release();
mRecorder = null;
}
}
if (soundStarted) {
// Compute a simple average of the amplitude over one
// second
int nMeasures = 100;
int sumAmpli = 0;
mRecorder.getMaxAmplitude(); // First call returns 0
int n = 0;
for (int i = 0; i < nMeasures; i++) {
if (mRecorder != null) {
int maxAmpli = mRecorder.getMaxAmplitude();
if (maxAmpli > 0) {
sumAmpli += maxAmpli;
n++;
}
} else {
return null;
}
try {
Thread.sleep(1000 / nMeasures);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
mRecorder.stop();
mRecorder.release();
mRecorder = null;
final float avgAmpli = (float) sumAmpli / n;
if (avgAmpli > MINIMUM_REQUIRED_AVERAGE) {
//TODO: Vibrate the device here
}
}
return null;
}
}
For more information regarding the detection of sound level, please refer to the following:
android: detect sound level
What does Android's getMaxAmplitude() function for the MediaRecorder actually give me?
Regarding the exception java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare(), that is happening because the Toast needs to run on the main thread of your app. If your Thread code (like an AsyncTask) is inside an Activity, you can try the following:
runOnUiThread(new Runnable() {
#Override
public void run() {
//Call your Toast here
}
});
Otherwise, you need to somehow pass the conclusion of your method to the Activity for it to run the Toast.
EDIT:
If you want to use this from a Button, you could set its OnClickListener on your Activity's onCreate() call and execute the AsyncTask there. For example:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout);
Button button = (Button)findViewById(R.id.your_button_id);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new DetectAmplitude().execute(new Void[]{});
}
});
}
I suggest you take a look at how AsyncTask works before using this in production code.
You want to sample the audio, and analyze it immediately.
MediaRecorder seems to high level for this, it only captures to file. You probably want to use AudioRecorder instead, as it gives direct access to the input samples.
In order to detect a specific tone, you can use the Goertzel algorithm on the input samples. Here is a C++ implementation I did years ago that could serve as an example.
In order to detect any sound over a certain threshold, you can use Root Mean Square analysis on the input samples and make it trigger once the loudness reaches your threshold. Here is a Python example that reacts to loud noises from a microphone.
Try this:
Btn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
v.post(new Runnable() {
#Override
public void run() {
vibrate.vibrate(800);
}
});
}
});
You can try this:
Handler handler;
Runnable r;
handler = new Handler();
r = new Runnable() {
public void run() {
Vibrator vib = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
vib.vibrate(500);
handler.postDelayed(r, 1000);
}
};
handler.post(r);

how to make a videoview NOT started automatically after prepared

I have created a videoview with a standard media controller on it. I was able to play the video by calling start() method in setOnPreparedListener, so the video will play automatically when it finished preparing it self.
However, what i want to do is to make the video stand-by (NOT playing automatically), so the user need to tap/click/touch the videoview to start the video.
I've done some googling, and i also tried to setOnTouchListener on my videoview and calling the start() method there. But the result is unexpected (and confusing as well), a pop up dialog appears and said "The video cant be played".
This is the complete code :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
txtTitle = (TextView)findViewById(R.id.txtTitle);
player = (VideoView)findViewById(R.id.player);
Bundle video = getIntent().getExtras();
if(video != null)
{
id = video.getString("id");
title = video.getString("title");
rtsp = video.getString("rtsp");
}
txtTitle.setText(title);
pDialog = new ProgressDialog(this);
pDialog.setTitle("Please Wait...");
pDialog.setMessage("Buffering...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
try {
// Start the MediaController
MediaController mediacontroller = new MediaController(this);
mediacontroller.setAnchorView(player);
// Get the URL from String VideoURL
Uri uri = Uri.parse(rtsp);
player.setMediaController(mediacontroller);
player.setVideoURI(uri);
player.setBackgroundColor(Color.WHITE);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
player.requestFocus();
player.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer arg0) {
// TODO Auto-generated method stub
pDialog.dismiss();
player.setBackgroundColor(Color.TRANSPARENT);
//the video will be played if i call the start() method here
}
});
player.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
// TODO Auto-generated method stub
//"The video cant be played" pop up dialog appeared, video wont start
player.start();
return false;
}
});
}
I got confuse because it can be played when i put the start() method in setOnPreparedListener but it couldn't when i put it in setOnTouchListener.
I don't know if this is related to the problem or not, but im buffering a youtube video (RTSP link) on my videoview.
Any help is appreciated, Thanks.
This should be a comment but my reputation is not high enough. I do not see you calling prepare() method so probably you are trying to invoke start() when player is in initialized state. You might try to set the onTouchListener of player object in the onPrepared() callback.

How to play mpg/3gp 5 sec video at start of application?

I am developing an application in which i want to play a short 5 seconds video at the startup. which is the best format 3gp, mpg or something else? i have generated a title activity. I wanted to play the video before title. Help please!!! Below is the code of my title activity.
public class Title extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.title);
setTitle("M.I.S.T");
this.setTitleColor(Color.BLUE);
View title = getWindow().findViewById(android.R.id.title);
View titleBar = (View) title.getParent();
titleBar.setBackgroundColor(Color.YELLOW);
Thread timer = new Thread(){
public void run(){
try{
sleep(3000);
}catch (InterruptedException e){
e.printStackTrace();
}finally{
Intent open= new Intent("com.congestion6.asad.MENU");
startActivity(open);
}
}
};
timer.start();
}
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
finish();
}
}
mpeg can be compressing the video over a range of different formats/algorithms/codecs and some are supported some are not. 3gp is just one and it is supported (although a very poor format).
Try encoding a video yourself that you'll see all different options. Usually mp4 on H264 works flawlessly on mobiles.

rtsp video performance as Browser triggered intent vs my application triggered intent

Hi I am creating an app which will play livestream.com's rtsp live channel.
I am launching the player using intent within my app as following:
iPlayer = new Intent(Intent.ACTION_VIEW);
//iPlayer.setType("video/*");
iPlayer.setData(Uri.parse(videoUrl));
startActivity(iPlayer);
When the media player is launched through my Application, the video performance is very poor. It stops for buffering every few seconds, plays for few seconds and pauses for buffering again.
ON the other hand, If I open the url in android browser (eg. http://m.livestream.com/abcalbania) it has a video tag on that page and triggers video player. THIS time, the video runs very smooth.
Any Idea why this might happen? And how this can be fixed?
I do not want to launch browser URL as intent.
This is done on Atmel cortex A9 chipset with Android 2.3.4
The problem is caused by the codecs that probably are not supported by your player.
for example i have a video created with MPEG Audio codec along with the H.264 video codec.
if i launch the video through my Application the video runs smoothly, but if i launch a video in Ooyala Hook Player it has a very poor performance, it plays the video every 3 seconds, the reason is that the stream use MPEG audio codec instead of AAC Audio codec that is supported.
You will find the answer with:
what codecs are used to create de video, and what are supported by
your player?
Use this code for smooth STREAM
String videoUrl = "rtmp://mystream";
Intent i = new Intent(android.content.Intent.ACTION_VIEW);
i.setDataAndType(Uri.parse(videoUrl), "video/*");
startActivity(i);
Why not you play this in your own activity, create activity and render the video view like
private String path2 = "rtsp://...";
Uri video = Uri.parse(path2);
mVideoView.setVideoURI(video);
mVideoView.setMediaController(new MediaController(this));
mVideoView.requestFocus();
mVideoView.postInvalidateDelayed(100);
mVideoView.start();
Also you can buffer before start playing maybe 5 secs and than successive buffering will be fast. you can control more thing by your own.
Android's MediaPlayer handle very well RTSP - don't open an external app - it's not necessary and product-wise wrong.
About your question - the browser might send another parameters to the video player that help the video play smooth, I didn't check it but it sounds like the only possible option for what you're describing. Example for the extra param might be the video resolution / encoding / size .. you can get all of them easily using MediaMetaDataRetriever.
If you don't want to use the native VideoView or MediaPlayer you can always add external player to your
app, like libVLC or Vitamio.
I recommend of using Vitamio, is really easy to use and integrate. LibVLC is in native code, it means you'll have to build it using ndk and add its libs to your project.
You can find here how to do that.
Android video view support RTSP urls well no need to pass intent to other application.Try out with this code, pass xml with declaration of video view and find it inside this activity.
public class VideoPlayer extends Activity
{
private VideoView mVideoView;
String videoURL="";
static Utility utility;
static Context context;
//MediaController mediaController;
//int iCurrentpostion=0;
int counter=0;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.tab_video_player);
setupViews();
}
private void setupViews()
{
context=VideoPlayer.this;
//utility=new Utility(VideoPlayer.this);
showProgressDialog("Please wait", "Loading video..");
//videoURL=getIntent().getExtras().getString("url");
mVideoView=(VideoView)findViewById(R.id.xvdvwTab);
// mediaController=new MediaController(context);
// mVideoView.setMediaController(mediaController);
mVideoView.setOnPreparedListener(new OnPreparedListener()
{
#Override
public void onPrepared(MediaPlayer mp)
{
utility.hideProgressDialog();
mVideoView.start();
mVideoView.requestFocus();
}
});
mVideoView.setOnCompletionListener(new OnCompletionListener()
{
#Override
public void onCompletion(MediaPlayer mp)
{
finish();
}
});
mVideoView.setOnErrorListener(new OnErrorListener()
{
#Override
public boolean onError(MediaPlayer mp, int what, int extra)
{
utility.hideProgressDialog();
return false;
}
});
playVideoFile();
}
private void playVideoFile()
{
try
{
mVideoView.setVideoURI(Uri.parse("your url"));
}
catch (Exception e)
{
utility.hideProgressDialog();
if (mVideoView != null)
{
mVideoView.stopPlayback();
}
}
}
#Override
protected void onResume()
{
/*if(mVideoView!=null)
{
//setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
mVideoView.requestFocus();
if(iCurrentpostion!=0)
mVideoView.seekTo(iCurrentpostion);
mVideoView.start();
}
super.onResume();*/
}
#Override
protected void onDestroy()
{
try
{
if (mVideoView != null)
{
mVideoView.stopPlayback();
mVideoView=null;
}
super.onDestroy();
} catch (Exception e)
{}
}
public void showProgressDialog(String title,String Message)
{
hideProgressDialog();
progressDialog=new ProgressDialog(mActivity);
progressDialog.setTitle(title);
progressDialog.setMessage(Message);
if(Constant.isActivityisRunning)
progressDialog.show();
}
public void hideProgressDialog()
{
if (progressDialog != null)
{
if (progressDialog.isShowing())
{
progressDialog.dismiss();
progressDialog = null;
}
}
}
}
I think play video by Asynchronously for better performance. My code is:
private class myAsync extends AsyncTask<Void, Integer, Void> {
int duration = 0;
//int current = 0;
#Override
protected Void doInBackground(Void... params) {
videoView.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
progressDialog.dismiss();
videoView.seekTo(check);
videoView.start();
duration = videoView.getDuration();
}
});
do {
current = videoView.getCurrentPosition();
System.out.println("duration - " + duration + " current- "
+ current);
}
if (sync.isCancelled())
break;
} while (current != duration || current == 0);
return null;
}
}

How to use the microphone on Android

I have just started to develop my first Android app, and I am having a hard time figuring out how to start the microphone and have it listen, which is a main feature of my app.
I've searched the Android docs and I can't find much info on this.
Thanks in advance.
Maybe this can help (actually from the Android docs):
Audio Capture
Create a new instance of android.media.MediaRecorder.
Set the audio source using MediaRecorder.setAudioSource(). You will probably want to use MediaRecorder.AudioSource.MIC.
Set output file format using MediaRecorder.setOutputFormat().
Set output file name using MediaRecorder.setOutputFile().
Set the audio encoder using MediaRecorder.setAudioEncoder().
Call MediaRecorder.prepare() on the MediaRecorder instance.
To start audio capture, call MediaRecorder.start().
To stop audio capture, call MediaRecorder.stop().
When you are done with the MediaRecorder instance, call MediaRecorder.release() on it. Calling MediaRecorder.release() is always recommended to free the resource immediately.
or:
Android Audio Recording Tutorial
You can use custom recorder:
final static int RQS_RECORDING = 1;
Uri savedUri;
Button buttonRecord;
#Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
buttonRecord = (Button) findViewById(R.id.record);
buttonRecord.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent(
MediaStore.Audio.Media.RECORD_SOUND_ACTION);
startActivityForResult(intent, RQS_RECORDING);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
if (requestCode == RQS_RECORDING) {
savedUri = data.getData();
Toast.makeText(MainActivity.this,
"Saved: " + savedUri.getPath(), Toast.LENGTH_LONG).show();
}
}

Categories

Resources