I want to implement video player (ExoPlayer) in my android app. Player must play video (not big, ~2-3 minutes) from some url. On nexus 5 it works well, but on phone "Samsung GT-I8552 Galaxy Win" unfortunately it doesnt work. There are exception logs after compiling and starting app:
Internal runtime error.
java.lang.IllegalStateException
at android.media.MediaCodec.dequeueOutputBuffer(Native Method)
And this is my code:
private SurfaceView surfaceView;
private ExoPlayer player;
private MediaCodecVideoTrackRenderer videoRenderer;
private MediaCodecAudioTrackRenderer audioRenderer;
private CustomMediaController mediaController;
private String userAgent;
private final int RENDERER_COUNT = 8;
private static final int BUFFER_SEGMENT_SIZE = 64 * 1024;
private static final int BUFFER_SEGMENT_COUNT = 256;
private static final int minBufferMs = 10000;
private static final int minRebufferMs = 5000;
private final String videoUrl_2 = "someurl...";
...
surfaceView = (SurfaceView) findViewById(R.id.surface_view);
player = ExoPlayer.Factory.newInstance(RENDERER_COUNT, minBufferMs, minRebufferMs);
userAgent = Util.getUserAgent(this, "MyPlayer");
Allocator allocator = new DefaultAllocator(BUFFER_SEGMENT_SIZE);
DataSource dataSource = new DefaultUriDataSource(context, null, userAgent);
ExtractorSampleSource sampleSource = new ExtractorSampleSource(Uri.parse(videoUrl_2), dataSource, allocator, BUFFER_SEGMENT_COUNT * BUFFER_SEGMENT_SIZE);
videoRenderer = new MediaCodecVideoTrackRenderer(context,
sampleSource, MediaCodecSelector.DEFAULT, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource, MediaCodecSelector.DEFAULT);
player.prepare(videoRenderer, audioRenderer);
player.sendMessage(videoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, surfaceView.getHolder().getSurface());
player.setPlayWhenReady(true);
CustomMediaPlayerControl customMediaPlayerControl = new CustomMediaPlayerControl(player);
mediaController = new CustomMediaController(context);
mediaController.setMediaPlayer(customMediaPlayerControl);
mediaController.setAnchorView(surfaceView);
mediaController.setEnabled(true);
My class CustomMediaPlayerControl:
public class CustomMediaPlayerControl implements MediaController.MediaPlayerControl {
private ExoPlayer player;
public CustomMediaPlayerControl(ExoPlayer player) {
this.player = player;
}
#Override
public void start() {
player.setPlayWhenReady(true);
}
#Override
public void pause() {
player.setPlayWhenReady(false);
}
#Override
public int getDuration() {
return (int) player.getDuration();
}
#Override
public int getCurrentPosition() {
return (int) player.getCurrentPosition();
}
#Override
public void seekTo(int pos) {
player.seekTo(pos);
}
#Override
public boolean isPlaying() {
return player.getPlayWhenReady();
}
#Override
public int getBufferPercentage() {
return (int) player.getBufferedPercentage();
}
#Override
public boolean canPause() {
return true;
}
#Override
public boolean canSeekBackward() {
return true;
}
#Override
public boolean canSeekForward() {
return true;
}
#Override
public int getAudioSessionId() {
return 0;
}
}
And my class CustomMediaController:
public class CustomMediaController extends MediaController {
private MediaController.MediaPlayerControl playerControl;
public CustomMediaController(Context context) {
super(context);
}
#Override
public void setMediaPlayer(MediaController.MediaPlayerControl playerControl) {
super.setMediaPlayer(playerControl);
this.playerControl = playerControl;
}
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
int keyCode = event.getKeyCode();
if (playerControl.canSeekForward() && keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
playerControl.seekTo(playerControl.getCurrentPosition() + 15000); // milliseconds
show();
}
return true;
} else if (playerControl.canSeekBackward() && keyCode == KeyEvent.KEYCODE_MEDIA_REWIND) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
playerControl.seekTo(playerControl.getCurrentPosition() - 5000); // milliseconds
show();
}
return true;
}
return super.dispatchKeyEvent(event);
}
}
ExoPlayer have a minimal sdk level 16 requirement.
ExoPlayer’s standard audio and video components rely on Android’s MediaCodec API, which was released in Android 4.1 (API level 16). Hence they do not work on earlier versions of Android.
From: https://google.github.io/ExoPlayer/guide.html
Related
I am trying to create a metronome sound, however, what isn't working is the ability to mute it. I would like the ability to mute it without stopping the TimerTask since I want the rate to be consistent once it is unmuted. Here is my code:
public class Metronome {
private boolean mute;
private boolean playing = false;
private Timer mainTimer;
private SoundPool mSoundPool;
int mSoundID;
public Metronome(Context context) {
mSoundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0);
mSoundID = mSoundPool.load(context, R.raw.metronome, 1);
}
public void play(float pace, boolean mute) {
mainTimer = new Timer();
MyTimerTask mainTimerTask = new MyTimerTask();
mainTimer.schedule(mainTimerTask, 0, Math.round(pace * 1000));
this.mute = mute;
playing = true;
}
public void stop() {
mainTimer.cancel();
mainTimer.purge();
playing = false;
}
public boolean isPlaying() {
return playing;
}
public void setMute(boolean mute) {
this.mute = mute;
if (mute) {
mSoundPool.setVolume(mSoundID, 0, 0);
} else {
mSoundPool.setVolume(mSoundID, 1, 1);
}
}
private void playSound() {
if (!mute) {
mSoundPool.play(mSoundID, 1, 1, 1, 0, 1);
}
}
class MyTimerTask extends TimerTask {
#Override
public void run() {
playSound();
}
}
}
However, calling setMute(true) does not work. Does anyone know how I can mute my SoundPool?
Figured it out. It works when I use static methods and variables.
public class Metronome {
public static boolean mute = false;
public static boolean playing = false;
private static Timer mainTimer;
private static SoundPool soundPool;
private static int soundID;
public static void loadSound(Context context) {
soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0);
soundID = soundPool.load(context, R.raw.metronome, 1);
}
public static void play(float pace, boolean isMuted) {
mainTimer = new Timer();
MyTimerTask mainTimerTask = new MyTimerTask();
mainTimer.schedule(mainTimerTask, 0, Math.round(pace * 1000));
mute = isMuted;
playing = true;
}
public static void stop() {
mainTimer.cancel();
mainTimer.purge();
playing = false;
}
static class MyTimerTask extends TimerTask {
#Override
public void run() {
playSound();
}
private void playSound() {
if (!mute) {
soundPool.play(soundID, 1, 1, 1, 0, 1);
}
}
}
}
I want to to add the media controller on VLC player android integration but i didn't find any option to do that i am sharing the code -
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.otherformat);
load = (ProgressBar) this.findViewById(R.id.load);
intent = getIntent();
load.setVisibility(View.VISIBLE);
handler = new Handler();
mFilePath ="http://mm2.pcslab.com/mm/7h800.mp4";
Log.e(TAG, "Playing: " + mFilePath);
mSurface = (SurfaceView) findViewById(R.id.surface);
holder = mSurface.getHolder();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setSize(mVideoWidth, mVideoHeight);
}
#Override
protected void onResume() {
super.onResume();
createPlayer(mFilePath);
}
#Override
protected void onPause() {
super.onPause();
releasePlayer();
}
#Override
protected void onDestroy() {
super.onDestroy();
releasePlayer();
}
/**
* Used to set size for SurfaceView
*
* #param width
* #param height
*/
private void setSize(int width, int height) {
mVideoWidth = width;
mVideoHeight = height;
if (mVideoWidth * mVideoHeight <= 1)
return;
if (holder == null || mSurface == null)
return;
int w = getWindow().getDecorView().getWidth();
int h = getWindow().getDecorView().getHeight();
boolean isPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
if (w > h && isPortrait || w < h && !isPortrait) {
int i = w;
w = h;
h = i;
}
float videoAR = (float) mVideoWidth / (float) mVideoHeight;
float screenAR = (float) w / (float) h;
if (screenAR < videoAR)
h = (int) (w / videoAR);
else
w = (int) (h * videoAR);
holder.setFixedSize(mVideoWidth, mVideoHeight);
ViewGroup.LayoutParams lp = mSurface.getLayoutParams();
lp.width = w;
lp.height = h;
mSurface.setLayoutParams(lp);
mSurface.invalidate();
}
/**
* Creates MediaPlayer and plays video
*
* #param media
*/
private void createPlayer(String media) {
releasePlayer();
try {
if (media.length() > 0) {
Toast toast = Toast.makeText(this, media, Toast.LENGTH_LONG);
toast.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0,
0);
//toast.show();
}
// Create LibVLC
// TODO: make this more robust, and sync with audio demo
ArrayList<String> options = new ArrayList<String>();
//options.add("--subsdec-encoding <encoding>");
options.add("--aout=opensles");
options.add("--audio-time-stretch"); // time stretching
options.add("-vvv"); // verbosity
libvlc = new LibVLC(this, options);
holder.setKeepScreenOn(true);
// Creating media player
mMediaPlayer = new MediaPlayer(libvlc);
mMediaPlayer.setEventListener(mPlayerListener);
mMediaPlayer.setVideoTrackEnabled(true);
// Seting up video output
final IVLCVout vout = mMediaPlayer.getVLCVout();
vout.setVideoView(mSurface);
//vout.setSubtitlesView(mSurfaceSubtitles);
vout.addCallback(this);
vout.attachViews();
Media m = new Media(libvlc, Uri.parse(media));
mMediaPlayer.setMedia(m);
mMediaPlayer.play();
////////////////////////////////////////////////
/* //mController = new MediaController(this);
mController = (MediaController)findViewById(R.id.mediaController);
mController.setVisibility(View.VISIBLE);
mController.setAnchorView(mSurface);
mController.show(0);*/
/*mController = new MediaController(this);
mController.setAnchorView(mSurface);
handler.post(new Runnable() {
public void run() {
mController.show();
}
});*/
} catch (Exception e) {
Log.e("Err", e.getMessage()+"");
Toast.makeText(this, "Error in creating player!"+e.getMessage(), Toast
.LENGTH_LONG).show();
}
}
private void releasePlayer() {
if (libvlc == null)
return;
mMediaPlayer.stop();
final IVLCVout vout = mMediaPlayer.getVLCVout();
vout.removeCallback(this);
vout.detachViews();
holder = null;
libvlc.release();
libvlc = null;
mVideoWidth = 0;
mVideoHeight = 0;
}
/**
* Registering callbacks
*/
private MediaPlayer.EventListener mPlayerListener = new MyPlayerListener(this);
#Override
public void onNewLayout(IVLCVout vout, int width, int height, int visibleWidth, int visibleHeight, int sarNum, int sarDen) {
if (width * height == 0)
return;
// store video size
mVideoWidth = width;
mVideoHeight = height;
setSize(mVideoWidth, mVideoHeight);
}
#Override
public void onSurfacesCreated(IVLCVout vout) {
}
#Override
public void onSurfacesDestroyed(IVLCVout vout) {
}
#Override
public void onHardwareAccelerationError(IVLCVout vlcVout) {
Log.e(TAG, "Error with hardware acceleration");
this.releasePlayer();
Toast.makeText(this, "Error with hardware acceleration", Toast.LENGTH_LONG).show();
}
private static class MyPlayerListener implements MediaPlayer.EventListener {
private WeakReference<OtherFormat> mOwner;
public MyPlayerListener(OtherFormat owner) {
mOwner = new WeakReference<OtherFormat>(owner);
}
#Override
public void onEvent(MediaPlayer.Event event) {
OtherFormat player = mOwner.get();
switch (event.type) {
case MediaPlayer.Event.EndReached:
Log.d(TAG, "MediaPlayerEndReached");
player.releasePlayer();
break;
case MediaPlayer.Event.Playing:
load.setVisibility(View.GONE);
break;
case MediaPlayer.Event.Paused:
case MediaPlayer.Event.Buffering:
float percent = event.getBuffering(); /* from 0.0f to 100f */
Log.e("Percent><><",""+percent);
break;
case MediaPlayer.Event.Stopped:
default:
break;
}
}
}}
XML for this activity -
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
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"
>
<SurfaceView
android:id="#+id/surface"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center" />
<ProgressBar
android:id="#+id/load"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:visibility="visible"
android:layout_gravity="center"
/>
<MediaController
android:id="#+id/mediaController"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" >
</MediaController>
</FrameLayout>
By this code mediacontrollers not showing please help me how to show media controllers for pause, play and seekbar for video position in surfaceview of vlc media player.
I had the same issue and have found a solution.
Sure, it's too late for answer, but maybe I will save some time to someone.
To add default media control you need to implement it in following way
remove MediaController from layout and add some container for media control to to your activity (it will be added programmatically).
<FrameLayout
android:id="#+id/video_surface_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:foregroundGravity="clip_horizontal|clip_vertical"
tools:ignore="true">
<SurfaceView
android:id="#+id/surface"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center" />
</FrameLayout>
add controller init to onStart activity or to onCreate
import android.widget.MediaController;
private MediaController controller;
#Override
protected void onStart() {
super.onStart();
....
controller = new MediaController(this);
controller.setMediaPlayer(findViewByid(R.id.video_surface_frame));
controller.setAnchorView(mVideoSurfaceFrame);
mVideoSurfaceFrame.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
controller.show(10000);
}
});
}
to define playerInterface, you need to implement the MediaController.MediaPlayerControl interface like this
private MediaController.MediaPlayerControl playerInterface = new MediaController.MediaPlayerControl() {
public int getBufferPercentage() {
return 0;
}
public int getCurrentPosition() {
float pos = mLibVlc.getPosition();
return (int)(pos * getDuration());
}
public int getDuration() {
return (int)mLibVlc.getLength();
}
public boolean isPlaying() {
return mLibVlc.isPlaying();
}
public void pause() {
mLibVlc.pause();
}
public void seekTo(int pos) {
mLibVlc.setPosition((float)pos / getDuration());
}
public void start() {
mLibVlc.play();
}
public boolean canPause() {
return true;
}
public boolean canSeekBackward() {
return true;
}
public boolean canSeekForward() {
return true;
}
#Override
public int getAudioSessionId() {
return 0;
}
};
launch your app and tap on video. You will see default media control and it will hide in 10 sec
Good luck!
Link to VideoLan sample on github:
https://code.videolan.org/videolan/vlc-android/blob/f3db2e4a33bf96c03056874322fb5b9304f92259/vlc-android/src/vlc/android/VLC.java
public class Show_Array extends AppCompatActivity implements IVLCVout.Callback {
private TextView container_extension;
private String stream_typee,stream_idd,container_extensionn ;
private String SAMPLE_URL = "";
public int mHeight;
public int mWidth;
private SurfaceView mVideoSurface = null;
private FrameLayout sdk;
private IVLCVout vlcVout;
private LibVLC mLibVlc = null;
private MediaPlayer mMediaPlayer = null;
private int flag = 0;
private ImageButton Resize;
private Media media;
private ArrayList<String> args;
private SurfaceHolder mSurfaceHolderVideo;
private MediaController controller;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.show__array);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
//Referances
Resize = findViewById(R.id.Resize);
mVideoSurface = findViewById(R.id.video_surface);
stream_typee = getIntent().getExtras().getString("stream_type");
stream_idd = getIntent().getExtras().getString("stream_id");
container_extensionn = getIntent().getExtras().getString("container_extension");
args = new ArrayList<>();
args.add("-vvv");
mLibVlc = new LibVLC(this, args);
mMediaPlayer = new MediaPlayer(mLibVlc);
vlcVout = mMediaPlayer.getVLCVout();
sdk = findViewById(R.id.sdk);
Resize_video();
setup_url();
controller = new MediaController(this);
controller.setMediaPlayer(playerInterface);
controller.setAnchorView(mVideoSurface);
mVideoSurface.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
controller.show(10000);
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
mMediaPlayer.release();
mLibVlc.release();
}
void Resize_video()
{
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
mHeight = displayMetrics.heightPixels;
mWidth = displayMetrics.widthPixels;
Resize.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
flag+=1;
int width = 1000;
int height = 560;
if(flag%2!=0) {
LinearLayout.LayoutParams myImageLayout = new LinearLayout.LayoutParams(width, height);
myImageLayout.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
sdk.setLayoutParams(myImageLayout);
vlcVout.setWindowSize(width,height);
}
else
{
LinearLayout.LayoutParams myImageLayout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
myImageLayout.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
sdk.setLayoutParams(myImageLayout);
vlcVout.setWindowSize(mWidth,mHeight);
}
}
});
}
void setup_url()
{
//TextView
container_extension = findViewById(R.id.URL);
if (stream_typee.equals("live"))
{
SAMPLE_URL = "http://uautv.ru:2095/"+stream_typee+"/webserver/6tE#BzW73#sX/"+stream_idd+".ts";
container_extension.setText( SAMPLE_URL);
}else
{
SAMPLE_URL = "http://uautv.ru:2095/"+stream_typee+"/webserver/6tE#BzW73#sX/"+stream_idd+"."+container_extensionn;
container_extension.setText( SAMPLE_URL);
}
}
#Override
protected void onStart() {
super.onStart();
vlcVout.setWindowSize(mWidth,mHeight);
vlcVout.setVideoView(mVideoSurface);
vlcVout.attachViews();
mMediaPlayer.getVLCVout().addCallback(this);
if(!SAMPLE_URL.isEmpty()) {
media = new Media(mLibVlc, Uri.parse(SAMPLE_URL));
mMediaPlayer.setMedia(media);
media.release();
mMediaPlayer.play();
}else
{
Toast.makeText(getApplicationContext(),"URL EMPTY",Toast.LENGTH_LONG).show();
}
}
#Override
protected void onStop() {
super.onStop();
mMediaPlayer.stop();
mMediaPlayer.getVLCVout().detachViews();
mMediaPlayer.getVLCVout().removeCallback(this);
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
#Override
public void onNewLayout(IVLCVout vlcVout, int width, int height, int visibleWidth, int visibleHeight, int sarNum, int sarDen)
{ }
#Override
public void onSurfacesCreated(IVLCVout vlcVout) {
}
#Override
public void onSurfacesDestroyed(IVLCVout vlcVout) {
}
private MediaController.MediaPlayerControl playerInterface = new MediaController.MediaPlayerControl() {
public int getBufferPercentage() {
return 0;
}
public int getCurrentPosition() {
float pos = mMediaPlayer.getPosition();
return (int)(pos * getDuration());
}
public int getDuration() {
return (int)mMediaPlayer.getLength();
}
public boolean isPlaying() {
return mMediaPlayer.isPlaying();
}
public void pause() {
mMediaPlayer.pause();
}
public void seekTo(int pos) {
mMediaPlayer.setPosition((float)pos / getDuration());
}
public void start() {
mMediaPlayer.play();
}
public boolean canPause() {
return true;
}
public boolean canSeekBackward() {
return true;
}
public boolean canSeekForward() {
return true;
}
#Override
public int getAudioSessionId() {
return 0;
}
};
}
I want to draw math-function like y=x^2+1 with androidPlot library.I have "SimpleXYPlot". It works but I don't know how to change it from sin to my function.
Here's the code:
public class DynamicXYPlotActivity extends Activity {
// redraws a plot whenever an update is received:
private class MyPlotUpdater implements Observer {
Plot plot;
public MyPlotUpdater(Plot plot) {
this.plot = plot;
}
#Override
public void update(Observable o, Object arg) {
plot.redraw();
}
}
private XYPlot dynamicPlot;
private MyPlotUpdater plotUpdater;
SampleDynamicXYDatasource data;
private Thread myThread;
#Override
public void onCreate(Bundle savedInstanceState) {
// android boilerplate stuff
super.onCreate(savedInstanceState);
setContentView(R.layout.dynamicxyplot_example);
// get handles to our View defined in layout.xml:
dynamicPlot = (XYPlot) findViewById(R.id.dynamicXYPlot);
plotUpdater = new MyPlotUpdater(dynamicPlot);
// only display whole numbers in domain labels
dynamicPlot.getGraphWidget().setDomainValueFormat(new DecimalFormat("0"));
// getInstance and position datasets:
data = new SampleDynamicXYDatasource();
SampleDynamicSeries sine1Series = new SampleDynamicSeries(data, 0, "Sine 1");
SampleDynamicSeries sine2Series = new SampleDynamicSeries(data, 1, "Sine 2");
LineAndPointFormatter formatter1 = new LineAndPointFormatter( Color.rgb(0, 0, 0), null, null, null );
formatter1.getLinePaint().setStrokeJoin(Paint.Join.ROUND);
formatter1.getLinePaint().setStrokeWidth(10);
dynamicPlot.addSeries( sine1Series,formatter1 );
LineAndPointFormatter formatter2 = new LineAndPointFormatter(Color.rgb(0, 0, 200), null, null, null);
formatter2.getLinePaint().setStrokeWidth(10);
formatter2.getLinePaint().setStrokeJoin(Paint.Join.ROUND);
//formatter2.getFillPaint().setAlpha(220);
dynamicPlot.addSeries(sine2Series, formatter2);
// hook up the plotUpdater to the data model:
data.addObserver(plotUpdater);
// thin out domain tick labels so they dont overlap each other:
dynamicPlot.setDomainStepMode(XYStepMode.INCREMENT_BY_VAL);
dynamicPlot.setDomainStepValue(5);
dynamicPlot.setRangeStepMode(XYStepMode.INCREMENT_BY_VAL);
dynamicPlot.setRangeStepValue(10);
dynamicPlot.setRangeValueFormat(new DecimalFormat("###.#"));
// uncomment this line to freeze the range boundaries:
dynamicPlot.setRangeBoundaries(-100, 100, BoundaryMode.FIXED);
// create a dash effect for domain and range grid lines:
DashPathEffect dashFx = new DashPathEffect(
new float[] {PixelUtils.dpToPix(3), PixelUtils.dpToPix(3)}, 0);
dynamicPlot.getGraphWidget().getDomainGridLinePaint().setPathEffect(dashFx);
dynamicPlot.getGraphWidget().getRangeGridLinePaint().setPathEffect(dashFx);
}
#Override
public void onResume() {
// kick off the data generating thread:
myThread = new Thread(data);
myThread.start();
super.onResume();
}
#Override
public void onPause() {
data.stopThread();
super.onPause();
}
class SampleDynamicXYDatasource implements Runnable {
// encapsulates management of the observers watching this datasource for update events:
class MyObservable extends Observable {
#Override
public void notifyObservers() {
setChanged();
super.notifyObservers();
}
}
private static final double FREQUENCY = 5; // larger is lower frequency
private static final int MAX_AMP_SEED = 100; //100
private static final int MIN_AMP_SEED = 10; //10
private static final int AMP_STEP = 1;
public static final int SINE1 = 0;
public static final int SINE2 = 1;
private static final int SAMPLE_SIZE = 30;
private int phase = 0;
private int sinAmp = 1;
private MyObservable notifier;
private boolean keepRunning = false;
{
notifier = new MyObservable();
}
public void stopThread() {
keepRunning = false;
}
//#Override
public void run() {
try {
keepRunning = true;
boolean isRising = true;
while (keepRunning) {
Thread.sleep(100); // decrease or remove to speed up the refresh rate.
phase++;
if (sinAmp >= MAX_AMP_SEED) {
isRising = false;
} else if (sinAmp <= MIN_AMP_SEED) {
isRising = true;
}
if (isRising) {
sinAmp += AMP_STEP;
} else {
sinAmp -= AMP_STEP;
}
notifier.notifyObservers();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public int getItemCount(int series) {
return SAMPLE_SIZE;
}
public Number getX(int series, int index) {
if (index >= SAMPLE_SIZE) {
throw new IllegalArgumentException();
}
return index;
}
public Number getY(int series, int index) {
if (index >= SAMPLE_SIZE) {
throw new IllegalArgumentException();
}
double angle = (index + (phase))/FREQUENCY;
double amp = sinAmp * Math.sin(angle);
switch (series) {
case SINE1:
return amp;
case SINE2:
return -amp;
default:
throw new IllegalArgumentException();
}
}
public void addObserver(Observer observer) {
notifier.addObserver(observer);
}
public void removeObserver(Observer observer) {
notifier.deleteObserver(observer);
}
}
class SampleDynamicSeries implements XYSeries {
private SampleDynamicXYDatasource datasource;
private int seriesIndex;
private String title;
public SampleDynamicSeries(SampleDynamicXYDatasource datasource, int seriesIndex, String title) {
this.datasource = datasource;
this.seriesIndex = seriesIndex;
this.title = title;
}
#Override
public String getTitle() {
return title;
}
#Override
public int size() {
return datasource.getItemCount(seriesIndex);
}
#Override
public Number getX(int index) {
return datasource.getX(seriesIndex, index);
}
#Override
public Number getY(int index) {
return datasource.getY(seriesIndex, index);
}
}
}
=======================================================
After what "Nick" said and other minor addition, I got this result:
but as we know :
https://www.google.com/search?q=y%3Dx%5E2%2B1&oq=y%3Dx%5E2%2B1&aqs=chrome..69i57j0l5.7056j0j7&sourceid=chrome&es_sm=93&ie=UTF-8
Now how to make the left side?
Using the code above can modify SampleDynamicXYDatasource to do what you want. All that code does is generate some data in a sine pattern. I don't know how your x values are going to be generated so here's a modified SampleDynamicXYDatasource.getY(...) that just uses the original code where x=index above and uses your function to generate the y-values:
public Number getY(int series, int index) {
if (index >= SAMPLE_SIZE) {
throw new IllegalArgumentException();
}
Number x = getX(series, index);
double y = Math.pow(x.doubleValue(), 2) + 1;
switch (series) {
case SINE1:
return y;
case SINE2:
return -y;
default:
throw new IllegalArgumentException();
}
}
You'll notice that when you make this change, the plot appears to no longer be animated. (it actually still is but that's besides the point) This is because y is now purely a function of x and the x values never change.
As far as how to stop the animation, the plot redraws whenever plot.redraw() is called, which in the example above is in response to an event being continuously fired by events generated by the thread being run on the Runnable instance of SampleDynamicXYDatasource. Using the example above, the simplest way to stop the animation is to replace:
#Override
public void onResume() {
// kick off the data generating thread:
myThread = new Thread(data);
myThread.start();
super.onResume();
}
with:
#Override
public void onResume() {
dynamicPlot.redraw();
super.onResume();
}
Try replace this>>
public Number getX(int series, int index) {
if (index >= SAMPLE_SIZE) {
throw new IllegalArgumentException();
}
return index;
}
To this>>
public Number getX(int series, int index) {
if (index >= SAMPLE_SIZE) {
throw new IllegalArgumentException();
}
return index - 15;
}
I have the following Live Wallpaper:
public class GLWallpaperVideoDemo extends GLWallpaperService {
public static final String folder = "video";
public static final String TAG = "GLWVD";
public static String videoName="VIDEOWALL.avi";
//video variables
public int videoWidth,videoHeight;
public boolean videoWideScreen=false;
VideoRenderer renderer = null;
public GLWallpaperVideoDemo() {
super();
Log.e(TAG,"constructor()");
}
#Override
public void onCreate() {
Log.e(TAG,"onCreate()");
super.onCreate();
//transfer video to sdcard
Log.d(TAG,"transferring video asset to sdcard");
copyVideoToCard();
Log.d(TAG,"transferred");
//if videoName == blankVideo, then don't load anything
//TODO
NativeCalls.initVideo();
Log.d(TAG,"Opening video");
NativeCalls.loadVideo("file:/"+"sdcard/"
+GLWallpaperVideoDemo.videoName);
//set video dimensions (now that we opened the video)
videoWidth = NativeCalls.getVideoWidth();
videoHeight = NativeCalls.getVideoHeight();
videoWideScreen = ( videoWidth > videoHeight ) ? true : false;
}
private VideoEngine mEngine=null;
#Override
public Engine onCreateEngine() {
Log.e(TAG,"onCreateEngine()");
mEngine = new VideoEngine();
return mEngine;
}
class VideoEngine extends GLEngine {
VideoEngine() {
super();
Log.e(TAG,"VideoEngine VideoEngine()");
if(renderer==null)renderer = new VideoRenderer(GLWallpaperVideoDemo.this,
this);
setRenderer(renderer);
//setRenderMode(RENDERMODE_WHEN_DIRTY);
setRenderMode(RENDERMODE_CONTINUOUSLY);
}
VideoRenderer getRenderer() { return renderer; }
}
}
And this is the renderer:
public class VideoRenderer implements GLWallpaperService.Renderer {
static private String TAG="Renderer>>>>>>>>>>>>";
static boolean runOnce = false;
//MediaPlayer mediaPlayer = MediaPlayer.create(MyApp.getContext(), R.raw.gunfireusedforboardstage);
//screen variables
int screenWidth=50,screenHeight=50;
int drawWidth, drawHeight; //dimensions of fit-to-screen video
int paddingX, paddingY; //padding for fit-to-screen-video
//texture variables
int powWidth,powHeight;
//pointers
GLWallpaperVideoDemo mParent;
GLWallpaperVideoDemo.VideoEngine mParentEngine;
//lock
static public Object lock = new Object();
//fps
long fpsTime;
public int framecount;
public VideoRenderer() {
super();
Log.e(TAG,"Constructor()");
}
public VideoRenderer(GLWallpaperVideoDemo p,
GLWallpaperVideoDemo.VideoEngine e) {
super();
mParent = p;
mParentEngine = e;
Log.e(TAG,"constructor()");
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
Log.e(TAG, "onSurfaceCreated()");
}
void process(int width, int height) {
setScreenDimensions( width, height );
Log.d(TAG,"Killing texture");
NativeCalls.closeOpenGL();
setTextureDimensions( screenWidth, screenHeight );
setFitToScreenDimensions( mParent.videoWidth,
mParent.videoHeight );
if ( !runOnce ) {
Log.e(TAG,"Preparing frame");
NativeCalls.prepareStorageFrame();
}
NativeCalls.initOpenGL();
runOnce = true;
}
//This gets called whenever you preview the wallpaper or set the
//wallpaper
public void onSurfaceChanged(GL10 gl, int width, int height) {
Log.e(TAG,"onSurfaceChanged()");
synchronized(lock) {
process(width, height);
}
}
public void onDrawFrame(GL10 gl) {
synchronized(lock) {
//Log.d(TAG,"Drawing ....");
NativeCalls.getFrame(); // from video
NativeCalls.drawFrame(); // using openGL
if(framecount>300)framecount=0;
framecount++;
//Log.e("framecount",Integer.toString(framecount));
if(framecount==117 || framecount==124 ||framecount==137 ||framecount==145||framecount==159||framecount==167)
{new Thread(new Runnable() {
public void run() {
MediaPlayer mp= MediaPlayer.create(MyApp.getContext(), R.raw.gunfireusedforboardstage);
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mp.release();
};
});
}
}).start();}
if (MyDebug.showFPS) {
final float fpsRate;
fpsRate = 1000f/((float) (SystemClock.uptimeMillis()
- fpsTime) );
fpsTime = SystemClock.uptimeMillis();
Log.d(TAG,
TAG+"drawFrame(): fps: "
+String.valueOf(fpsRate)
);
}
}
}
Now you see the variable framecount inside the renderer?
It gets reinitialized every time open the settings of the Wallpaper !!!
The result is that the renderer continues its work, but framecount is set again to 0,
the consequence is that the frames are not in sync with the MediaPlayer anymore.
SOLVED:
I made the variable static :-)
i have problem with live wallpaper on preview mode.ie the wallpaper image doesn't fit well in landscape mode.it works great on portrait.i need your help.hope you would help me.i have added code
RajawaliRenderer.java
public class RipplesRenderer extends RajawaliRenderer {
private final int NUM_CUBES_H = 4;
private final int NUM_CUBES_V = 4;
private final int NUM_CUBES = NUM_CUBES_H * NUM_CUBES_V;
//private Animation3D[] mAnims;
private TouchRippleFilter mFilter;
private long frameCount;
private final int QUAD_SEGMENTS = 40;
int mScreenHeight,
mScreenWeight;
Gallery_Activity mm;
boolean flag_check = false;
int pos = 0;
int viewBackgroundImageName;
Bitmap texture;
SimpleMaterial planeMat;
int randPosition=1;
int change_value;
int Ripple_number,speed1;
Preferences preferences;
private MediaPlayer myplayer;
private boolean sound;
public RipplesRenderer(Context context) {
super(context);
setFrameRate(50);
this.mContext=context;
randPosition = BitmapUpdate.randomGenerator;
texture = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.gthree_one);
//sp=mContext.getSharedPreferences("wallpapersettings",0);
preferences=new Preferences(mContext);
}
protected void initScene() {
if(randPosition!=1) {
texture = BitmapUpdate.bit;
}
mCamera.setPosition(0, 0, -9);
DirectionalLight light = new DirectionalLight(0, 0, 1);
light.setPower(1f);
BaseObject3D group = new BaseObject3D();
DiffuseMaterial material = new DiffuseMaterial();
material.setUseColor(true);
mScreenHeight = GNWallpaper.hieght;
mScreenWeight = GNWallpaper.weight;
Random rnd = new Random();
planeMat = new SimpleMaterial();
Plane plane=new Plane(9,7,1,1);
//Plane plane = new Plane(4, 4, 1, 1);
plane.setRotZ(-90);
plane.setScale(1.0f);
plane.setMaterial(planeMat);
addChild(plane);
mFilter = new TouchRippleFilter();
mPostProcessingRenderer.setQuadSegments(QUAD_SEGMENTS);
mPostProcessingRenderer.setQuality(PostProcessingQuality.MEDIUM);
addPostProcessingFilter(mFilter);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
if (pos != com.themebowlapp.galaxynote3livewallpaper.Gallery_Activity.wallpaper_position || randPosition != BitmapUpdate.randomGenerator) {
texture = BitmapUpdate.bit;
pos = com.themebowlapp.galaxynote3livewallpaper.Gallery_Activity.wallpaper_position;
randPosition = BitmapUpdate.randomGenerator;
}
Ripple_number=preferences.getSpeed_controler();
speed1=Ripple_number*100;
super.onSurfaceCreated(gl, config);
}
public void onDrawFrame(GL10 glUnused) {
super.onDrawFrame(glUnused);
mFilter.setTime((float) frameCount++ *.05f);
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
super.onSurfaceChanged(gl, width, height);
mFilter.setScreenSize(width, height);
mFilter.setRippleSize((40+speed1));
planeMat.addTexture(mTextureManager.addTexture(texture));
}
public void setTouch(float x, float y) {
mFilter.addTouch(x, y, frameCount *.05f);
}
#Override
public void onTouchEvent(MotionEvent event) {
final int action = event.getAction();
if(event.getAction() == MotionEvent.ACTION_DOWN) {
//sound
myplayer = MediaPlayer.create(getContext(), R.raw.water_drop);
myplayer.setVolume(100, 100);
myplayer.start();
myplayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer myplayer) {
myplayer.release();
}
});
setTouch(event.getX() / mScreenWeight, 1.0f - (event.getY() / mScreenHeight));
}
super.onTouchEvent(event);
}
}
Settings.java
public class Settings extends Activity {
public TextView SettingTextObj, BackgroundTextObj;
private RelativeLayout chose_background;
public Preferences preferences;
Context cont = this;
private CheckBox soundcheckbox;
private String PREFRENCES_NAME;
SharedPreferences settings;
// private Button choosebackground;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings);
chose_background = (RelativeLayout) findViewById(R.id.BackgroundLayoutId);
BackgroundTextObj = (TextView) findViewById(R.id.backgroundTxtViewId);
soundcheckbox = (CheckBox)findViewById(R.id.checkBox1);
settings = getSharedPreferences(PREFRENCES_NAME, 0);
Boolean isChecked = settings.getBoolean("cbx1_ischecked", false);
soundcheckbox.setChecked(isChecked);
soundcheckbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
private MediaPlayer myplayer;
#Override
public void onCheckedChanged(CompoundButton arg0, boolean isChecked) {
Editor editor = getSharedPreferences(PREFRENCES_NAME, 0).edit();
editor.putBoolean("cbx1_ischecked", isChecked);
editor.commit();
Toast.makeText(getApplicationContext(), "Check", Toast.LENGTH_SHORT).show();
myplayer = MediaPlayer.create(getBaseContext(), R.raw.water_drop);
myplayer.setVolume(100, 100);
myplayer.start();
}
});
preferences = new Preferences(cont);
chose_background.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
final String[] items = { "Phone Gallery", "Choose Background" };
AlertDialog.Builder builder = new AlertDialog.Builder(
Settings.this);
builder.setTitle("Pick a Background");
builder.setItems(items, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int item) {
if (items[item].equals(items[0])) {
startActivity(new Intent(Settings.this, PhoneGallery_Activity.class));
} else {
startActivity(new Intent(Settings.this, Gallery_Activity.class));
}
}
});
AlertDialog alert = builder.create();
alert.show();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.settings, menu);
return true;
}
}
GNWallpaper.java
public class GNWallpaper extends Wallpaper {
private RipplesRenderer mRenderer;
private String imageBg;
private int cvwidth;
private int cvheight;
private int visibleWidth;
private Bitmap bg;
private String LoadText;
private boolean sound;
private MediaPlayer myplayer;
public static WindowManager display;
static int height,width;
//private Integer[] mImageIds = { R.drawable.gthree_one,R.drawable.gthree_two,R.drawable.gthree_three, R.drawable.gthree_four, R.drawable.gthree_five, R.drawable.gthree_six,};
private int position;
public Engine onCreateEngine() {
display =(WindowManager) getSystemService(Context.WINDOW_SERVICE);
height= display.getDefaultDisplay().getHeight();
width= display.getDefaultDisplay().getWidth();
mRenderer = new RipplesRenderer(this);
//Log.i("shibbu"," hello");
return new WallpaperEngine(this.getSharedPreferences(SHARED_PREFS_NAME,
Context.MODE_PRIVATE), getBaseContext(), mRenderer, false);
}
public void onSharedPreferenceChanged(SharedPreferences prefs,
String key) {
imageBg = prefs.getString("image_custom", "Bad Image");
getBackground();
sound=prefs.getBoolean("pref_sound", false);
// //sound
// sound=prefs.getBoolean("pref_sound", false);
}
void getBackground() {
if (this.cvwidth == 0 || this.cvheight == 0 || this.visibleWidth == 0) {
this.cvwidth = 1290;
this.cvheight = 800;
this.visibleWidth = 1290;
}
if(new File(imageBg).exists()) {
int SampleSize = 1;
do {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
bg = BitmapFactory.decodeFile(imageBg, options);
SampleSize = (int) (Math.ceil(options.outWidth/(this.visibleWidth * 2))*2);
options.inJustDecodeBounds = false;
try {
options.inSampleSize = SampleSize;
bg = BitmapFactory.decodeFile(imageBg, options);
} catch (OutOfMemoryError e) {
SampleSize = SampleSize * 2;
}
} while (bg == null);
bg = Bitmap.createScaledBitmap(bg, this.cvwidth/2, this.cvheight, true);
} else {
bg = BitmapFactory.decodeResource(getResources(), R.drawable.gthree_one);
//bg = BitmapFactory.decodeResource(getResources(), mImageIds[position]);
//position++;
bg = Bitmap.createScaledBitmap(bg, this.cvwidth/2, this.cvheight, true);
LoadText = "";
}
}
}
Refer this link.It will help you to change to landscape view..
http://tips4android.blogspot.in/2012/01/android-tips-how-to-get-screen.html