I'am trying to develop app for tv streaming (HLS). Using code below I tested stream on 2.3.3, 3.0 and 4.0.1 version Android devices, but encountered several problems.
On Android 2.3.3 stream plays for >1 minute and then just stops. On Android 3.0 it plays well and on Android 4.0.3 it displays message 'This file cannot be played' (if I remember correctly).
So my question would be:
How can I play stream on ether of these devices, without having stream playing problems? Or where can I read more about solutions to these problems (tried to search but found nothing useful)?
Code in Main_Activity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
VideoView player = (VideoView)findViewById(R.id.player);
String httpLiveUrl = "http://aj.lsops.net/live/aljazeer_en_high.sdp/playlist.m3u8";
//for Android 2.3.3 I used httplive:// prefix
player.setVideoURI(Uri.parse(httpLiveUrl));
player.setMediaController(new MediaController(this));
player.requestFocus();
player.start();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
Code in xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<VideoView
android:id="#+id/player"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true" />
</RelativeLayout>
Sorry if my english is poor.
Thank You.
This will not solve all the streaming issues. But one thing you should do is call player.start() when the MediaPlayer is ready. The selected answer to this SO post sets a listener on the MediaPlayer object so that it will run start() when onPrepared(MediaPlayer mp) is called.
Insert this Code to AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
Related
This is an issue in MacBook Pro. I figured out the problem after few
hours of debugging
I am using the following code to create a media player and play an mp3 file. I am using the built-in emulator in Android Studio. Any suggestions for debugging?
import android.media.MediaPlayer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
MediaPlayer mediaPlayer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mediaPlayer = MediaPlayer.create(this,R.raw.music);
mediaPlayer.start();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.ablejohnson.audiodemo.MainActivity">
</android.support.constraint.ConstraintLayout>
EDIT
For further debugging I added an onErrorListener for mediaPlayer
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mediaPlayer, int what, int extra) {
Log.e("error","what:"+what+",extra"+extra);
return false;
}
});
The following line is getting printed in logs.
D/Atlas: Validating map...
E/MediaPlayer: Should have subtitle controller already set
E/MediaPlayer: Error (1,-19)
E/error: what:1,extra-19
This is a specific issue in Emulator running on MacBook Pro. I tried to run the same app on actual devices and windows+ emulator both cases it was working fine.
The solution here is hacky but it worked for me
turn off Bluetooth and relaunch the emulated device
I quote the documentation, "A "raw" resource is a file that the system does not try to parse in any particular way. However, the content of this resource should not be raw audio. It should be a properly encoded and formatted media file in one of the supported formats."
Check if your music file is in a supported format.
Check out the doc for further details.
https://developer.android.com/guide/topics/media/mediaplayer.html
Support format:
https://developer.android.com/guide/topics/media/media-formats.html
We're trying to play audio alerts from our android app (traffic information) over bluetooth connected car stereos. If we switch the car stereo audio input to bluetooth, the app audio plays. If it is on any other source, the app audio does not play, either from the stereo or from the device.
What we want to do, is to allow users to keep the stereo audio input on DAB/FM radio or other source, but have our app audio interrupt at certain times and play these traffic information alerts, like how VOIP apps manage to do (such as Facebook messenger), and the built-in telephony phone call app manages to do.
Here is the code we are using at the moment :
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>
We have these additional permissions in android manifest :
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
We would greatly appreciate any advice on how to achieve this, thanks :)
We only need to support newer versions of android if necessary.
I was able to get it working with the following code :
audioM.setMode(audioM.MODE_IN_COMMUNICATION);
audioM.setBluetoothScoOn(true);
audioM.startBluetoothSco();
audioM.setSpeakerphoneOn(false);
And the following permissions :
<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" />
There was no need to set thread priority or request audio focus.
Note that I'm currently getting a 15 second delay between calling TextToSpeech.speak() and hearing the audio over the car radio. When I've solved that I'll update this answer.
To reach to any solution for your problem, we must understand first what facility does car audio system provides with bluetooth.
Car audio system support A2DP profile along with HandsFree profile for attaining calls. Now, when bluetooth is selected as the source anything which is played by your app on A2DP profile will be played by audio system. However, once you've switched to other source like radio, even though your device is connected with A2DP profile with car audio system nothing will be played which you are facing now. However, few things that can be tried here, which interrupts the radio play as well are:
We know that when any call comes, we get alert with phone number even when we are listening to radio. This alert portion you can use for your solution. However, I dont know much if we can send phone ring alert from app. These alerts are at lower level just AT commands. Some search would be needed to check this.
In some car audio system, there is facility that when sms comes it alerts you. This alert part can also be explored.
I could see these two option which could help you. But this is not the only option I guess. Please try to find car audio systems bluetooth spec sheet. There you could know what other bluetooth alert features they provide.
I will update this answer I find any hint on my above suggestion.
Thanks
Out there, there are a lot of examples about how to play video on Android (API level 16).
But I can't understand why they don't work for me.
This is a simple example:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="my.owm.package" >
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".ContentActivity"
android:label="#string/title_activity_content" >
</activity>
</application>
</manifest>
activity_content.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="my.owm.package.ContentActivity"
android:orientation="vertical">
<VideoView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/videoView"
android:layout_gravity="center_horizontal" />
</LinearLayout>
contentActivity.java
public class ContentActivity extends Activity {
private static final String TAG = ContentActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_content);
VideoView videoView =(VideoView) findViewById(R.id.videoView);
MediaController mediaController = new MediaController(this);
mediaController.setAnchorView(videoView);
videoView.setVideoPath("/sdcard/Movies/test.mp4");
videoView.setMediaController(mediaController);
videoView.requestFocus();
videoView.start();
}
}
The test.mp4 files is actually there and runs fine with any player (btw it's a H264 w/ Baseline Profile). Anyway i tried several other videos, most of them used by the authors of the tutorial on this topic.
I get no errors but no video and no audio.
I'm pretty sure I'm missing something obvious because I found this code in a lot of Android tutorials!
Any idea?
Thanks!
EDIT:
I run the code on a physical device.
However I discovered the code is actually working until I add the following item in the layout xml file:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_margin="0dp" />
I worked on this way :
public class AnVideoView extends Activity {
String SrcPath = "/sdcard/Video/Android in Spaaaaaace!_low.mp4";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
VideoView myVideoView = (VideoView)findViewById(R.id.myvideoview);
myVideoView.setVideoPath(SrcPath);
myVideoView.setMediaController(new MediaController(this));
myVideoView.requestFocus();
myVideoView.start();
}
}
I also have come across issues with VideoView like this across multiple devices before.
Firstly I would consider re-encoding your videos using a tool such as ffmpeg that can be downloaded here.
The following encoding has always worked for me:
ffmpeg -i input.mp4 -c:v libx264 -profile:v baseline -c:a libfaac -ar 44100 -ac 2 -b:a 128k -movflags faststart output.mp4
Alternatively, some devices cannot handle videos with 'large' dimensions. Try resizing your videos to a smaller size and seeing if that helps also.
SOLVED: the DrawerLayout should be added at the END of the layout... it seems the order is important!
I've been making a soundboard app of my infant son's sounds. The app simply opens to MainActivity class where it displays a scrollable list of buttons that, when pressed, will playback a pre-recorded MP3 of my son screaming something.
Once it's debugging or running on my Nexus 7 there is a Choreographer error and somewhere between 50 and 90 frames are skipped. The warning is that the 'application may be doing too much work on its main thread'. On my device three random buttons refuse to play sound until the app is closed and re-opened but then another three random buttons refuse to work. This problem didn't occur when my app only had eight buttons in a simple LinearLayout (without ScrollView).
I'm a beginner to both java and Android programming but, from what I guess, my laughably poor code is taking too much memory to properly function. My question is either, how would you code a scrollable list of 33 buttons that play their own sound, or could someone teach me how to better my code, please?
MainActivity.java (showing only the first three buttons/sounds for this question):
import android.media.MediaPlayer;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.Button;
import android.view.View;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final MediaPlayer ahh = MediaPlayer.create(this, R.raw.ahh);
final MediaPlayer dededeh = MediaPlayer.create(this, R.raw.dededeh);
final MediaPlayer neganegabunbunbug = MediaPlayer.create(this, R.raw.naganagbunbun);
Button bahh = (Button) this.findViewById(R.id.Ahhhbutton);
bahh.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ahh.start();
}
});
}
}
And the activity_main.xml (again with only the first three buttons for this question):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tab1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin" >
<ScrollView
android:id="#+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<Button
android:id="#+id/Ahhhbutton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:background="#layout/button_shape"
android:text="#string/button1a"
android:textColor="#d1d1d1"
android:textSize="20sp" />
<Button
android:id="#+id/dededehbutton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:background="#layout/button_shape"
android:text="#string/button1b"
android:textColor="#d1d1d1"
android:textSize="20sp" />
<Button
android:id="#+id/neganegabunbunbugbutton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:background="#layout/button_shape"
android:text="#string/button1c"
android:textColor="#d1d1d1"
android:textSize="20sp" />
Button bdededeh = (Button) this.findViewById(R.id.dededehbutton);
bdededeh.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dededeh.start();
}
});
Button bnaganagbunbun = (Button) this.findViewById(R.id.naganagabunbutton);
bnaganagbunbun.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
neganegabunbunbug.start();
}
});
</LinearLayout>
</ScrollView>
</LinearLayout>
It's not the layout. As your error said, you shouldn't do any long-term work on the Main-Thread.
The main-thread (or on Android the UI-Thread) handles interaction with the user. For the UI to not freeze and feel fast, you should execute long-term actions off the UI-Thread.
Also, the problem is not the actual playback, but you loading all media-files:
MediaPlayer.create(this, R.raw.ahh);
As the docs for the create()-method suggest:
[...] When done with the MediaPlayer, you should call release(), to
free the resources. If not released, too many MediaPlayer instances
will result in an exception.
For the "off the UI-Thread"-thing, you have three options:
Directly can create a Runnable-implementing class that plays your sound and submit it to a ScheduledThreadPoolExecuter (maximum control, more code).
Use an AsyncTask (Android exclusive) to play the song (fairly simple).
If you want the sound-playback to continue even when the app is not currently in the foreground, use a Service (most work)
So, what you should do is:
Store a List of your raw-file references (the R.raw.ahh) and don't load them directly.
When a song is selected for playback, call create() on that songs ID and start playback off the UI-Thread.
When done, call release() to release the resources.
I'm having problems with this. If I go to an SWF directly in the browser, it works fine. If I attempt to use loadUrl on an SWF file it stays blank and loads nothing.
Figured it out. You have to enable plugins.
webview.getSettings().setPluginsEnabled(true);
Niky, you have a code example here.
I have used this example to test this code and confirm it works. In this example the qualibus.swf is in contained within the assets of the app. Please test this on an actual device, as on the emulator it show a blank page (probably the flash player is not present on the emulator)
Test3Activity.java:
package com.blabla.test3;
import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;
public class Test3Activity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String url ="file:///android_asset/qualibus.swf";
WebView wv=(WebView) findViewById(R.id.webView1);
wv.getSettings().setPluginsEnabled(true);
wv.loadUrl(url);
}
}
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<WebView android:id="#+id/webView1"
android:layout_width="match_parent"
android:layout_height="match_parent">
</WebView>
</LinearLayout>
Result:
The function WebView.getSettings().setPluginsEnabled(); method has
been deprecated since API level 9, and was removed in API level 18.
You can use the newer function
WebView.getSettings().setPluginState(WebSettings.PluginState.ON);
which was added in API level 8 and was deprecated in API level 18.
According to the WebSettings Documentation API levels beyond 18 will
not support plugins; I'm assuming it's because the main plugin to
support was flash which adobe is no longer developing for mobile.
Quoted from source
So, for now you can use it till 18, and handle compatibility with higher APIs (sadly)