I have RecyclerView inside a Fragment. The RecyclerView's every item has a ProgressBar. In the itemView's onClick listener a MediaPlayer plays a sound. I want to indicate the MediaPlayer's progress with a ProgressBar, which is inside the same ViewHolder. How can I achieve this?
I have tried to work in the Activity's runOnUiThread, but the ProgressBar stops in the beginning.
#Override
public void onClick(View view) {
if(mMediaPlayer.isPlaying())
{
mMediaPlayer.stop();
}
try {
mMediaPlayer.reset();
mMediaPlayer.setDataSource(mContext,mSound.getSoundUri());
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
mMediaPlayer.start();
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
final int duration = mMediaPlayer.getDuration();
final int amoungToupdate = duration / 100;
Timer mTimer = new Timer();
mTimer.schedule(new TimerTask() {
#Override
public void run() {
((MainActivity)mContext).runOnUiThread(new Runnable() {
#Override
public void run() {
if (!(amoungToupdate * mProgressBar.getProgress() >= duration)) {
int p = mProgressBar.getProgress();
p += 1;
mProgressBar.setProgress(p);
}
}
});
};
}, amoungToupdate);
}
});
}
Here the xml example code where imageview and progress bar are in center of its parent relative layout, you could change its view as you like.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ProgressBar
android:id="#+id/progress"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginBottom="50dp"
android:layout_centerInParent="true" />
<ImageView
android:id="#+id/pic"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:contentDescription="#string/todo" />
</RelativeLayout>
When your video is done with loading you can hide the progress bar like this.
viewHolder.progressBar.setVisibility(View.GONE);
Related
I want to hide ImageView Thumbnail after Remote Video ready to play, means when onPrepared execute but imageView.setVisibility(View.GONE) doesn't works at all.
I have seen this answers one, two and I think cause is SurfaceView or VideoView. as per answers
I have tried using both MediaPlayer and VideoView
code using MediaPlayer and SurfaceView
mMediaPlayer = new MediaPlayer();
holder.surfaceView.setDrawingCacheEnabled(true);
try {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setDataSource(mContext, Uri.parse(video_url));
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
((Activity)mContext).runOnUiThread(new Runnable() {
#Override
public void run() {
holder.imgThumbnail.getParent().requestTransparentRegion(holder.imgThumbnail);
holder.imgThumbnail.setVisibility(View.GONE);
holder.imgThumbnail.getParent().requestTransparentRegion(holder.imgThumbnail);
}
});
Toast.makeText(mContext,"onPrepared",Toast.LENGTH_LONG).show();
}
});
} catch (IllegalArgumentException | SecurityException | IllegalStateException | IOException e) {
e.printStackTrace();
}
mMediaPlayer.prepareAsync();
XML of SurfaceView
<RelativeLayout
android:layout_width="410dp"
android:id="#+id/v_view"
android:visibility="visible"
android:layout_height="307.50dp">
<SurfaceView
android:id="#+id/video_view"
android:layout_width="410dp"
android:layout_height="307.50dp"
/>
<ImageView
android:id="#+id/imgThumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible"
android:scaleType="centerCrop" />
</RelativeLayout>
code using VideoView
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
Log.i(TAG,"onPrepared");
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
videoView.start();
Toast.makeText(mContext,"start video",Toast.LENGTH_LONG).show();
((Activity)mContext).runOnUiThread(new Runnable() {
#Override
public void run() {
holder.imgThumbnail.getParent().
requestTransparentRegion(holder.imgThumbnail);
holder.imgThumbnail.setVisibility(View.GONE);
holder.imgThumbnail.getParent().
requestTransparentRegion(holder.imgThumbnail);
}
});
}
},100);
}
});
XML of VideoView
<RelativeLayout
android:layout_width="410dp"
android:id="#+id/v_view"
android:visibility="visible"
android:layout_height="307.50dp">
<VideoView
android:id="#+id/video_view"
android:layout_width="410dp"
android:layout_height="307.50dp"
/>
<ImageView
android:id="#+id/imgThumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
android:background="#color/back_orange"
android:scaleType="centerCrop" />
</RelativeLayout>
Please help! I'm stuck
I want to show a ProgressBar while MediaPlayer is preparing to play and when MediaPlayer starts playing ProgressBar disappear .
this is my code
public class MainActivity extends Activity {
String path="http://live.mp3quran.net:8006/;";
Button play_button, pause_button;
MediaPlayer player =new MediaPlayer();
private ProgressBar mProgress;
#Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
play_button=(Button)findViewById(R.id.play_button);
pause_button=(Button)findViewById(R.id.pause_button);
mProgress=(ProgressBar)findViewById(R.id.progressBar);
mProgress.setVisibility(View.INVISIBLE);
play_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mProgress.setVisibility(View.VISIBLE);
try {
player.setDataSource(path);
player.prepare();
player.start();
} catch (IOException e) {
e.printStackTrace();
}
finally {
if(mProgress.getVisibility()==View.VISIBLE)
mProgress.setVisibility(View.INVISIBLE);
}
}
});
pause_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
player.stop();
player.reset();
}
});
}
}
my XML file Code
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
<Button android:id="#+id/play_button"
android:layout_width="120px"
android:layout_height="60px"
android:layout_marginTop="60px"
android:gravity="center"
android:text="Play" />
<Button android:id="#+id/pause_button"
android:layout_width="120px"
android:layout_height="60px"
android:layout_alignParentRight="true"
android:layout_marginTop="60px"
android:text="Pause" />
<ProgressBar
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/progressBar"
android:layout_alignBottom="#+id/text_shown"
android:layout_toRightOf="#+id/play_button"
android:layout_toLeftOf="#+id/pause_button"
android:max="100"
android:progress="20"
android:layout_toStartOf="#+id/pause_button" />
</RelativeLayout>
My problem is that ProgressBar doesn't appear.
I have tried this solution
How can i show a ProgressBar when mediaPlayer is prepairing to play
but it doesn't help.
You can use like this
final ProgressDialog ringProgressDialog = ProgressDialog.show(this, "Please wait ...", "Fetching your contact..", true);
ringProgressDialog.setCancelable(true);
new Thread(new Runnable() {
#Override
public void run() {
try {
// Here you should write your time consuming task...
// Let the progress ring for 10 seconds...
readContact();
// Thread.sleep(300);
} catch (Exception e) {
}
ringProgressDialog.dismiss();
}
}).start();
I am hiding the VideoView initially and when the video is loaded I am showing the VideoView. But onPrepared is never called if the VideoView is invisible initially. However onPrepared is called properly if VideoView is visible. Is there any way to hide the videoView until video is loaded. Any help would be appreciated. Thanks!
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<VideoView
android:id="#+id/video"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:visibility="invisible" />
</RelativeLayout>
MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
VideoView videoView = (VideoView) findViewById(R.id.video);
Uri videoUri = Uri.parse(url);
videoView.setVideoURI(videoUri);
videoView.requestFocus();
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
Toast.makeText(mActivity, "on prepared", Toast.LENGTH_SHORT).show();
videoView.setVisibility(View.VISIBLE);
}
});
}
You could try setting alpha channel of video view to 0 or close to 0.
Solved it making its layout invisible instead of videoView itself.
Thanks to #J.Kowalski .
Layout:
<FrameLayout
android:id="#+id/layout_video_view"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<VideoView
android:id="#+id/video_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:scrollbars="none"/>
</FrameLayout>
<ProgressBar
android:id="#+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone"
/>
Set OnPreparedListener:
videoView.setOnPreparedListener(this);
Show progress bar before ready:
#Override
public void showProgress() {
progress.setVisibility(View.VISIBLE);
layoutVideoView.setVisibility(View.INVISIBLE);
}
Load video URI:
#Override
public void loadVideo(Uri uri) {
videoView.setVideoURI(uri);
}
When its ready, onPrepared is called:
#Override
public void onPrepared(MediaPlayer mp) {
Log.d("debug", "onPrepared");
iStepPreviewPresenter.onVideoViewReady();
}
Finally show layout and start video:
#Override
public void hideProgress() {
progress.setVisibility(View.INVISIBLE);
layoutVideoView.setVisibility(View.VISIBLE);
}
#Override
public void startVideo() {
videoView.start();
}
Nailed it!
It can be achieved by one of these tricks
You can set the height and width of the VideoView to 1px until the video is prepared and then switch to full screen by changing the properties to match parent
As #FDIM said in his answer, we can set the alpha value of the view to 0 until video is prepared. But it works only if we use TextureView to load the video. It doesn't work with normal VideoView. Here is a custom VideoView extending TextureView which mimics the default VideoVideo implementation. This class can be directly used in xml file and can set the alpha to 0 to hide the video.
public class TextureVideoView extends TextureView implements SurfaceTextureListener {
private MediaPlayer mMediaPlayer;
public TextureVideoView(Context context) {
super(context);
init();
}
public TextureVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mMediaPlayer = new MediaPlayer();
this.setSurfaceTextureListener(this);
}
public void seekTo(int msec) {
mMediaPlayer.seekTo(msec);
}
public void setVideoPath(final String path) throws IOException {
mMediaPlayer.reset();
mMediaPlayer.setDataSource(path);
mMediaPlayer.prepare();
}
public void setVideoPath(FileDescriptor fd, long offset, long length) throws IOException {
mMediaPlayer.reset();
mMediaPlayer.setDataSource(fd, offset, length);
mMediaPlayer.prepare();
}
public void setVideoURI(Context context, Uri uri) throws IOException {
mMediaPlayer.reset();
mMediaPlayer.setDataSource(context, uri);
}
public void setOnPreparedListener(OnPreparedListener onPreparedListener) {
mMediaPlayer.setOnPreparedListener(onPreparedListener);
}
public void setOnCompletionListener(OnCompletionListener onCompletionListener) {
mMediaPlayer.setOnCompletionListener(onCompletionListener);
}
public void setOnErrorListener(OnErrorListener onErrorListener) {
mMediaPlayer.setOnErrorListener(onErrorListener);
}
public void start() {
mMediaPlayer.start();
}
public void pause() {
mMediaPlayer.pause();
}
public void setVolume(float leftVolume, float rightVolume ) {
mMediaPlayer.setVolume(leftVolume, rightVolume);
}
public boolean isPlaying() {
return mMediaPlayer.isPlaying();
}
public void stopPlayback() {
mMediaPlayer.stop();
}
public void reset() {
mMediaPlayer.reset();
}
public void release() {
mMediaPlayer.release();
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
int height) {
mMediaPlayer.setSurface(new Surface(surface));
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
int height) {
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
An easier workaround:
Just add a dummy parentview for the videoview and set the visiblity for that parentview instead of changing the visibility of the videoview itself.
I have a VideoView and a TextView on the same activity. Here s the xml for the layout.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rellayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<VideoView
android:id="#+id/videoview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:padding="5dp" />
<TextView
android:id="#+id/numberTicker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#color/purple"
android:textStyle="bold"
android:gravity="top|right"
android:textSize="35dp"
android:maxEms="3"/>
</RelativeLayout>
As soon as the video start playing I wish to display a number on the numberTicker text view. Mind you the numbers are likely to change 4 times per second. Anyway, the primary issue I have is to identify that the video has started playing and to keep updating the TextView.
My attempt :
vid = (VideoView) findViewById(R.id.videoview);
ratings = (TextView) findViewById(R.id.ratingTicker);
vid.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
vid.start();
vid.postDelayed(onEveryQuarterSecond,250);
}
});
...
...
private Runnable onEveryQuarterSecond = new Runnable() {
Random r = new Random();
int uVal, aVal;
#Override
public void run() {
ratings.setText(Integer.toString(r.nextInt()));
}
};
The code Runnable would only run once, and never get updated.
Am I missing something?
Thanks for the help!
You get a MediaPlayer object in onPrepared(). You could use that like this:
vid.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
this.mediaPlayer = mp; //have mediaPlayer be a class variable
vid.start();
vid.postDelayed(onEveryQuarterSecond,250);
}
});
private Runnable onEveryQuarterSecond = new Runnable() {
Random r = new Random();
int uVal, aVal;
#Override
public void run() {
while(mediaPlayer.isPlaying()) {
ratings.setText(Integer.toString(r.nextInt()));
Thread.sleep(250);
}
}
};
Consider to use a new Thread to not block the main UI Thread:
public void updateEverySecond() {
new Thread(new Runnable() {
#Override
public void run() {
while (mediaPlayer.isPlaying()) {
try {
ratings.setText(Integer.toString(r.nextInt()));
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
}
I need to show a second activity after the progress bar is filled. I tried the code below but it doesn't show the progress bar and just shows my second activity.
This is the code:
public class MiSuper2 extends Activity {
String strListas[] = null;
private ProgressBar mProgress;
private int mProgressStatus = 0;
private Handler mHandler = new Handler();
private StoreData stdArticulos = null;
public Cursor cursor = null;
private long fileSize = 0;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
stdArticulos = new StoreData(this);
fileSize = 0;
setContentView(R.layout.main);
stdArticulos = new StoreData(this);
cursor = stdArticulos.leerArticulos();
mProgress = (ProgressBar) findViewById(R.id.progressbar_activity);
new Thread(new Runnable() {
public void run() {
while (mProgressStatus < 100) {
mProgressStatus = doWork();
mHandler.post(new Runnable() {
public void run() {
mProgress.setProgress(mProgressStatus);
}
});
}
}
}).start();
if(cursor.moveToFirst()) {
do{
strListas[cursor.getPosition()] = cursor.getString(cursor.getPosition());
}while(cursor.moveToNext());
}
Intent intent = new Intent(MiSuper2.this, PntArticulo.class);
startActivity(intent);
}
public int doWork() {
while (fileSize <= 1000000) {
fileSize++;
return (int) fileSize;
}
return 100;
}
}
This is the 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="fill_parent"
android:gravity="center_horizontal"
android:orientation="vertical" >
<ImageView
android:id="#+id/imvLogo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/presentacion"
android:contentDescription="#string/logo"/>
<ProgressBar
android:id="#+id/progressbar_activity"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="200dp"
android:layout_height="wrap_content" android:layout_marginTop="100dp"/>
</LinearLayout>
Please help
It looks like you are using the doWork() function to take up time so that you're progress bar does something. Even though you wrote a big loop, it still executes very quickly so you don't see your progress bar move. Rather, you want to simulate your Thread doing something computationally intensive by using Thread.sleep() which takes an argument that is the time to sleep in milliseconds.
Try changing your code to this:
new Thread(new Runnable() {
public void run() {
while (mProgressStatus < 100) {
try {
mProgressStatus += doWork();
} catch (InterruptedException e) {
e.printStackTrace();
}
mHandler.post(new Runnable() {
public void run() {
mProgress.setProgress(mProgressStatus);
}
});
}
runOnUiThread(new Runnable() {
#Override
public void run() {
startActivity(new Intent(MiSuper2.this, Second.class));
}
});
}
}).start();
And...
public int doWork() throws InterruptedException {
Thread.sleep(1000);
return 1;
}
This will increment your progress bar by 1% every second. And finally, the documentation on Thread.sleep(): https://developer.android.com/reference/java/lang/Thread.html#sleep(long)
EDIT: Ramz beat me to this answer, but doesn't provide an explanation of why it's the answer. Hopefully my explanation helps.
EDIT2: I think you edited your questions since I started looking at it a second time. You had some errors in your XML before, but now it is gone. Regardless, your problem is now that you need the call to startActivity() inside your worker thread. Otherwise, the UI thread does not wait for the doWork() function to return and immediately starts the other Activity when your app starts. Sorry, I should have mentioned this before. The code I posted above is updated with this change.
Please try this code SplashScreen.java
package com.cud.point;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.ProgressBar;
import android.widget.TextView;
public class SplashScreen extends Activity {
ProgressBar bar;
TextView txt;
int total=0;
boolean isRunning=false;
// handler for the background updating
Handler handler=new Handler() {
#Override
public void handleMessage(Message msg) {
total=total+20;
String perc=String.valueOf(total).toString();
txt.setText(perc+"% completed");
bar.incrementProgressBy(20);
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
bar=(ProgressBar)findViewById(R.id.progress);
txt=(TextView)findViewById(R.id.txt);
Handler x = new Handler();
x.postDelayed(new SplashHandler(), 5000);
}
class SplashHandler implements Runnable
{
public void run() {
// TODO Auto-generated method stub
startActivity(new Intent(getApplication(),YourSecound Activity.class));
SplashScreen.this.finish();
}
}
public void onStart() {
super.onStart();
// reset the bar to the default value of 0
bar.setProgress(0);
// create a thread for updating the progress bar
Thread background=new Thread(new Runnable() {
public void run() {
try {
for (int i=0;i<5 && isRunning;i++) {
// wait 100ms between each update
Thread.sleep(1000);
handler.sendMessage(handler.obtainMessage());
}
}
catch (Throwable t) {
} } });
isRunning=true;
// start the background thread
background.start();
}
public void onStop() {
super.onStop();
isRunning=false;
}
}
splash.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="15px" >
<TextView
android:id="#+id/textView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Loading......" />
<TextView
android:id="#+id/txt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/imageView1"/>
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/splash" />
<ProgressBar
android:id="#+id/progress"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/imageView1"
android:layout_alignLeft="#+id/imageView1"
android:max="100" />
</RelativeLayout>
this is an example of my project so please make necessary change in xml file