The problem is that when I'm in the game, and click the Home button, the gameLoop thread (I guess) gets messed up and then it pops up "Unfortunately, 'app name' has stopped."
I've made a very simple program where this problem occurs. All this program does is showing a number on the screen, and increasing it when you touch the screen.
When I comment out view.onDraw(c) in GameLoopThread, everything seems to run nicely.
Error message:
FATAL EXEPTION: Thread-23207
java.lang.NullPointerExeption
at com.example.crashtest.GameView.onDraw(GameView.java:61)
at com.example.crashtest.GameLoopThread.run(GameLoopThread.java:34)
Here's the code:
MainActivity.java
package com.example.crashtest;
import android.os.Bundle;
import android.app.Activity;
import android.content.res.Configuration;
import android.view.KeyEvent;
import android.view.Window;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new GameView(this));
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
return true;
case KeyEvent.KEYCODE_MENU:
return true;
case KeyEvent.KEYCODE_VOLUME_UP:
return true;
case KeyEvent.KEYCODE_VOLUME_DOWN:
return true;
default:
return false;
}
}
}
GameView.java
package com.example.crashtest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GameView extends SurfaceView {
private SurfaceHolder holder;
private GameLoopThread gameLoopThread;
private int num = 0;
public GameView(final Context context) {
super(context);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
gameLoopThread.setRunning(false);
while (retry) {
try {
gameLoopThread.join();
retry = false;
} catch (InterruptedException e) {}
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
makeThread();
gameLoopThread.start();
gameLoopThread.setRunning(true);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
});
}
private void makeThread() {
gameLoopThread = new GameLoopThread(this);
}
#SuppressLint({ "WrongCall", "DrawAllocation" })
#Override
protected void onDraw(Canvas canvas) {
// Draw black background - Write variable 'num' on the screen
canvas.drawColor(Color.BLACK);
Paint paint = new Paint();
paint.setARGB(255, 0, 255, 0);
paint.setTextSize(50);
paint.setTextAlign(Align.CENTER);
canvas.drawText(Integer.toString(num), getWidth() / 2, getHeight() / 2, paint);
}
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
// Increase 'num' with 1 every touch
num++;
}
return super.onTouchEvent(event);
}
}
GameLoopThread.java
package com.example.crashtest;
import android.annotation.SuppressLint;
import android.graphics.Canvas;
public class GameLoopThread extends Thread {
static final long FPS = 10;
private GameView view;
public boolean running = false;
public boolean pause = false;
public GameLoopThread(GameView view) {
this.view = view;
}
public void setRunning(boolean run) {
running = run;
}
#SuppressLint("WrongCall")
#Override
public void run() {
long ticksPS = 1000 / FPS;
long startTime = 0;
long sleepTime = 0;
while (running) {
Canvas c = null;
startTime = System.currentTimeMillis();
try {
c = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
view.onDraw(c);
}
} finally {
if (c != null) {
view.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime = ticksPS-(System.currentTimeMillis() - startTime);
try {
if (sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
} catch (Exception e) {}
}
}
}
Look what you need when you close the Activity you need to stop your thread from my code implemented before see it :
GameView gameView ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
gameView = new GameView(this);
setContentView(gameView);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
gameView.StopView();
}
and you need to implement method called StopView() in your GameView like this
public void StopView() {
if (gameLoopThread != null) {
gameLoopThread.setRunning(false);
}
}
the problem because you still call the run method in thread after you try to block the thread and so you need to stop it before to block it using join.
i tested your code with new implementation and it work well with me , feed me back
Related
I am trying to play some rtsp video on custom textureview.Video is playing for the first time but when I go to second activity where the same video is played (not reinstantiated,same session but with different textureview) there it is playing and coming back to first activity where I am setting the sureface again in onResume textureview is still showing the content where it was left for the first time.Interesting fact is like video is still playing, just it is not visible in the textureview and if I go to second screen like before it is showing.I tried both releasing the surfacetexture and not releasing, tried also releasing the surface which I am holding a reference in the first activity for future use, not any of those seems to work.What can be the possible reason?
in onResume I am checking if app is coming back from app drawer or full screen activity.Where making the app go to background by clicking home button and coming back to app from app drawer video is playing.Only when coming back from full screen it's not working.
StreamingActivity.java
package com.wiznsystems.android.activities;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.SurfaceTexture;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.TextureView;
import android.view.View;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.myeglu.android.R;
import com.myeglu.zoomview.ZoomTextureView;
import com.wiznsystems.android.App;
import com.wiznsystems.android.data.objects.FFMPEG;
import com.wiznsystems.android.utils.Constants;
import com.wiznsystems.android.utils.Events;
import com.wiznsystems.android.utils.FFMPEGPlayer;
import java.io.File;
import de.greenrobot.event.EventBus;
import hugo.weaving.DebugLog;
import timber.log.Timber;
/**
* An example full-screen activity that shows and hides the system UI (i.e.
* status bar and navigation/system bar) with user interaction.
*/
#SuppressWarnings("JniMissingFunction")
public class StreamingActivity extends Fragment implements TextureView.SurfaceTextureListener{
private static boolean loadedLibraries;
private boolean comingFromAppDrawer;
private boolean isComingFromFullScreen;
boolean anotherVideo=false;
boolean shouldTextureUpdate=false;
Surface surface;
public StreamingActivity(){
}
public static ZoomTextureView surfaceView;
private ProgressBar progressBar;
public static boolean isPlaying;
private int isInitialized;
public static int isFullScreenDisplayed=0;
private String url;
public boolean isFirstTime;
private FFMPEG ffmpeg;
private FrameLayout frameLayout;
private final String TAG=StreamingActivity.class.getSimpleName();
int w=0,h=0;
private boolean isFirstTimeForFullscreen=true;
private Button fullScreenButton;
FFMPEGPlayer ffmpegPlayer;
String buttonText="";
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EventBus.getDefault().register(this);
url=getArguments().getString("url");
Log.d("ANURAN",url);
//getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
ffmpegPlayer=App.getFFMPEG();
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.activity_streaming,null,false);
surfaceView = (ZoomTextureView) view.findViewById(R.id.textureView);
frameLayout=(FrameLayout)view.findViewById(R.id.streaming_framelayout);
progressBar = ((ProgressBar)view.findViewById(R.id.progressBar));
fullScreenButton=(Button)view.findViewById(R.id.fullScreenButton);
fullScreenButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
isFullScreenDisplayed = 1;
isComingFromFullScreen = true;
shouldTextureUpdate=true;
if (isFirstTimeForFullscreen) {
//ffmpegPlayer.libSetSurface(null);
isFirstTimeForFullscreen = false;
}
//surfaceView.getSurfaceTexture().release();
//surface.release();
progressBar.setVisibility(View.INVISIBLE);
goFullScreen();
} catch (Exception throwable) {
throwable.printStackTrace();
}
}
});
progressBar.setVisibility(View.VISIBLE);
Log.d("ANURAN","onCreateView called");
surfaceView.setSurfaceTextureListener(this);
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//Log.d(TAG,url);
}
#DebugLog
private void postInit() {
Events.PlayButtonBGChanger playButtonBGChanger=new Events.PlayButtonBGChanger();
if (isInitialized==0) {
playButtonBGChanger.setShouldChange(true);
initPlay();
progressBar.setVisibility(View.GONE);
} else if(isInitialized==-999){
playButtonBGChanger.setShouldChange(false);
progressBar.setVisibility(View.INVISIBLE);
Snackbar.make(frameLayout,"Please make sure you have stopped other playing videos before playing this one.",Snackbar.LENGTH_LONG).show();
}
else {
playButtonBGChanger.setShouldChange(false);
Snackbar.make(frameLayout,"Something went wrong while live streaming.Please try again later.",Snackbar.LENGTH_LONG).show();
}
EventBus.getDefault().post(playButtonBGChanger);
}
private void initPlay() {
try {
int[] res = ffmpegPlayer.libGetVideoRes();
Log.d("ANURAN", "res width " + res[0] + ": height " + res[1]);
if (res[0] <= 0) {
res[0] = 480;
}
if (res[1] <= 0) {
res[1] = 320;
}
int[] screenRes = getScreenRes();
int width, height;
float widthScaledRatio = screenRes[0] * 1.0f / res[0];
float heightScaledRatio = screenRes[1] * 1.0f / res[1];
if (widthScaledRatio > heightScaledRatio) {
//use heightScaledRatio
width = (int) (res[0] * heightScaledRatio);
height = screenRes[1];
} else {
//use widthScaledRatio
width = screenRes[0];
height = (int) (res[1] * widthScaledRatio);
}
Log.d(TAG, "width " + width + ",height:" + height);
w=width;
h=height;
updateSurfaceView(width, height);
try{
ffmpegPlayer.libSetup(width,height);
if(this.surface == null){
Log.d("ANURAN","surface is null");
}
if(anotherVideo)
ffmpegPlayer.libSetSurface(null);
ffmpegPlayer.libSetSurface(surface);
Log.d("ANURAN","libsetsurface set initPlay()");
}catch (Exception throwable){
Toast.makeText(getActivity(),"Something went wrong while live streaming.Try again",Toast.LENGTH_SHORT).show();
}
playMedia();
}catch (Exception throwable){
throwable.printStackTrace();
}
}
public FFMPEGPlayer getFFMPEGPlayer(){
return this.ffmpegPlayer;
}
private void playMedia() {
if(progressBar.getVisibility()==View.VISIBLE){
progressBar.setVisibility(View.GONE);
}
try{
ffmpegPlayer.libPlay();
}catch (Exception throwable){
Toast.makeText(getActivity(),"Something went wrong while live streaming.Try again",Toast.LENGTH_SHORT).show();
}
isPlaying = true;
CamerasActivity.isPlaying=true;
}
#DebugLog
private void updateSurfaceView(int pWidth, int pHeight) {
//update surfaceview dimension, this will cause the native window to change
Log.d("ANURAN UPDATE SURFACE", "width " + pWidth + ",height:" + pHeight);
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) surfaceView.getLayoutParams();
params.width = pWidth;
params.height = pHeight;
surfaceView.setLayoutParams(params);
surfaceView.requestLayout();
}
#DebugLog
#SuppressLint("NewApi")
private int[] getScreenRes() {
int[] res = new int[2];
Display display = getActivity().getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
res[0] = size.x;
res[1] = size.y;
return res;
}
public void stopPlaying() {
isPlaying = false;
try{
ffmpegPlayer.libStop();
// ffmpegPlayer.libSetSurface(null);
// surfaceView.getSurfaceTexture().release();
// surfaceView.getSurfaceTexture().detachFromGLContext();
}catch (Exception throwable){
}
}
#Override
public void onStop() {
// Toast.makeText(getActivity(),"onStop called",Toast.LENGTH_SHORT).show();
// stopPlaying();
comingFromAppDrawer=true;
// if(surfaceView.getSurfaceTexture() !=null){
// surfaceView.getSurfaceTexture().release();
//
// }
// if(surface !=null){
// surface.release();
// surface=null;
// }
// if(isFullScreenDisplayed==0){
// stopPlaying();
// }
Log.d("ANURAN onStop",surface.isValid()+"");
super.onStop();
}
#Override
public void onPause() {
// Toast.makeText(getActivity(),"onStop called",Toast.LENGTH_SHORT).show();
// stopPlaying();
isComingFromFullScreen=true;
super.onPause();
}
#Override
public void onResume() {
super.onResume();
if(isComingFromFullScreen){
progressBar.setVisibility(View.INVISIBLE);
if(surface !=null){
ffmpegPlayer.libSetSurface(null);
Log.d("ANURAN onResume","value of surface "+surface.isValid());
ffmpegPlayer.libSetSurface(surface);
}
}
else if(comingFromAppDrawer){
//stopPlaying();
progressBar.setVisibility(View.INVISIBLE);
if(surface !=null){
ffmpegPlayer.libSetSurface(null);
//ffmpegPlayer.libSetup(w,h);
ffmpegPlayer.libSetSurface(surface);
}
}
}
#Override
public void onDestroy() {
super.onDestroy();
stopPlaying();
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
if(this.surface !=null) {
this.surface.release();
this.surface=null;
}
this.surface=new Surface(surface);
Log.d("ANURAN","surfacetexture available streaming activity");
new PlayVideo().execute();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
Log.d("ANURAN","surfacetexturesize changed streaming activity");
try{
w=width;
h=height;
this.surface.release();
this.surface=null;
this.surface=new Surface(surface);
if(isComingFromFullScreen){
//surfaceView.getHolder().getSurface().release();
updateSurfaceView(width, height);
ffmpegPlayer.libSetup(width,height);
ffmpegPlayer.libSetSurface(this.surface);
}
}catch (Exception throwable){
Toast.makeText(getActivity(),"Something went wrong while live streaming.Try again",Toast.LENGTH_SHORT).show();
}
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
Log.d("ANURAN","surfacetexture destroyed streaming activity");
// surfaceView.getSurfaceTexture().release();
// if(this.surface !=null){
// this.surface.release();
// this.surface=null;
// }
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
Log.d("ANURAN","surfacetexture updated streaming activity");
if(this.surface !=null){
this.surface.release();
this.surface=null;
this.surface=new Surface(surface);
}else{
this.surface=new Surface(surface);
}
}
public class PlayVideo extends AsyncTask<Void,Void,Void>{
#Override
protected Void doInBackground(Void... voids) {
try{
isInitialized=ffmpegPlayer.libInit(url);
}catch (Exception e){
e.printStackTrace();
Snackbar.make(frameLayout,"Exception Occured",Snackbar.LENGTH_SHORT).show();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
isFirstTime=false;
postInit();
this.cancel(true);
}
}
public void onEvent(FFMPEG ffmpeg){
url = ffmpeg.getUrl();
progressBar.setVisibility(View.VISIBLE);
//stopPlaying();
anotherVideo=true;
new PlayVideo().execute();
}
public void onEvent(Events.UpdateUrl newurl){
url=newurl.getUrl();
}
public void onEvent(Events.StopPlayback event){
stopPlaying();
}
public void onEvent(Events.NotifyPlayer notifyPlayer){
Snackbar.make(frameLayout,"Please stop any running video before playing another one",Toast.LENGTH_SHORT).show();
}
private void goFullScreen(){
Intent intent=new Intent(getContext(),FullScreenActivity.class);
Bundle bundle=new Bundle();
bundle.putString("url",url);
intent.putExtras(bundle);
getActivity().startActivity(intent);
}
}
FullScreenActivity.java
package com.wiznsystems.android.activities;
import android.annotation.SuppressLint;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.myeglu.android.R;
import com.myeglu.zoomview.AngleView;
import com.myeglu.zoomview.MatrixChangeListener;
import com.myeglu.zoomview.ZoomTextureView;
import com.wiznsystems.android.App;
import com.wiznsystems.android.data.objects.FFMPEG;
import com.wiznsystems.android.utils.FFMPEGPlayer;
import uk.copywitchshame.senab.photoview.gestures.PhotoViewAttacher;
import hugo.weaving.DebugLog;
/**
* Created by anuran on 9/3/18.
*/
#SuppressWarnings("JniMissingFunction")
public class FullScreenActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener, PhotoViewAttacher.OnMatrixChangedListener {
private ZoomTextureView surfaceView;
public static AngleView angleView;
private ProgressBar progressBar;
private PhotoViewAttacher photoViewAttacher;
public static boolean isPlaying;
private boolean isInitialized;
private String url;
private FrameLayout frameLayout;
Surface surface;
private final String TAG=StreamingActivity.class.getSimpleName();
public int backCounter=0;
FFMPEGPlayer ffmpegPlayer;
boolean fromADorSL=false;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_fullscreen);
surfaceView = (ZoomTextureView) findViewById(R.id.textureView);
angleView=(AngleView)findViewById(R.id.render_angle_view);
surfaceView.setSurfaceTextureListener(this);
frameLayout=(FrameLayout)findViewById(R.id.streaming_framelayout);
progressBar = ((ProgressBar)findViewById(R.id.progressBar));
progressBar.setVisibility(View.VISIBLE);
url=getIntent().getExtras().getString("url");
//new PlayVideo().execute();
ffmpegPlayer= App.getFFMPEG();
Log.d("ANURAN","fullscreen onCreate");
}
// #DebugLog
// private void postInit() {
// if (isInitialized) {
// initPlay();
// progressBar.setVisibility(View.GONE);
// } else {
// finish();
// }
// }
// private void initPlay() {
//
// try{
// int[] res = FFMPEGPlayer.libGetVideoRes();
// Log.d("ANURAN", "res width " + res[0] + ": height " + res[1]);
// if (res[0] <= 0) {
// res[0] = 480;
// }
// if (res[1] <= 0) {
// res[1] = 320;
// }
// int[] screenRes = getScreenRes();
// int width, height;
// float widthScaledRatio = screenRes[0] * 1.0f / res[0];
// float heightScaledRatio = screenRes[1] * 1.0f / res[1];
// if (widthScaledRatio > heightScaledRatio) {
// //use heightScaledRatio
// width = (int) (res[0] * heightScaledRatio);
// height = screenRes[1];
// } else {
// //use widthScaledRatio
// width = screenRes[0];
// height = (int) (res[1] * widthScaledRatio);
// }
// Log.d(TAG, "width " + width + ",height:" + height);
// updateSurfaceView(width, height);
// FFMPEGPlayer.libSetup(width, height);
// playMedia();
//
// photoViewAttacher = new PhotoViewAttacher(surfaceView, width, height);
// photoViewAttacher.setScaleType(ImageView.ScaleType.CENTER_CROP);
// photoViewAttacher.setOnMatrixChangeListener(this);
// photoViewAttacher.update();
// }catch (Exception e){
//
// }
// }
// private void playMedia() {
//
// try{
// if(progressBar.getVisibility()==View.VISIBLE){
// progressBar.setVisibility(View.GONE);
// }
// FFMPEGPlayer.libPlay();
// isPlaying = true;
// CamerasActivity.isPlaying=true;
// }catch (Exception e){
//
// }
// }
// #DebugLog
// private void updateSurfaceView(int pWidth, int pHeight) {
// //update surfaceview dimension, this will cause the native window to change
// Log.d("ANURAN UPDATE SURFACE", "width " + pWidth + ",height:" + pHeight);
// FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) surfaceView.getLayoutParams();
// params.width = pWidth;
// params.height = pHeight;
// surfaceView.setLayoutParams(params);
// }
#Override
public void onBackPressed() {
if(backCounter==1){
super.onBackPressed();
}else{
//surface.release();
StreamingActivity.isFullScreenDisplayed=0;
surfaceView.getSurfaceTexture().release();
//ffmpegPlayer.libSetSurface(null);
if(this.surface !=null){
this.surface.release();
this.surface=null;
}
backCounter++;
Toast.makeText(FullScreenActivity.this,"Press back again to quit full screen",Toast.LENGTH_SHORT).show();
}
}
#DebugLog
#SuppressLint("NewApi")
private int[] getScreenRes() {
int[] res = new int[2];
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
res[0] = size.x;
res[1] = size.y;
return res;
}
private void stopPlaying() {
isPlaying = false;
try{
ffmpegPlayer.libStop();
}catch (Exception e){
}
}
#Override
public void onStop() {
super.onStop();
fromADorSL=true;
}
#Override
public void onResume() {
super.onResume();
if(fromADorSL){
ffmpegPlayer.libSetSurface(null);
ffmpegPlayer.libSetSurface(this.surface);
}
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
//Toast.makeText(FullScreenActivity.this,"SurfaceTexture available",Toast.LENGTH_SHORT).show();
//updateSurfaceView(width, height);
try{
this.surface=new Surface(surface);
ffmpegPlayer.libSetup(width, height);
ffmpegPlayer.libSetSurface(this.surface);
photoViewAttacher = new PhotoViewAttacher(surfaceView, width, height);
photoViewAttacher.setScaleType(ImageView.ScaleType.CENTER_CROP);
photoViewAttacher.setOnMatrixChangeListener(this);
photoViewAttacher.update();
progressBar.setVisibility(View.INVISIBLE);
angleView.setVisibility(View.VISIBLE);
}catch (Exception e){
}
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
try{
Toast.makeText(FullScreenActivity.this,"SurfaceTexture changed",Toast.LENGTH_SHORT).show();
if (photoViewAttacher != null ) {
photoViewAttacher.update ();
}
if(this.surface !=null){
this.surface.release();
}
this.surface=null;
this.surface=new Surface(surface);
ffmpegPlayer.libSetup(width,height);
ffmpegPlayer.libSetSurface(this.surface);
}catch (Exception e){
}
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
try{
// this.surface.release();
// this.surface=null;
surfaceView.getSurfaceTexture().release();
if(this.surface !=null){
this.surface.release();
this.surface=null;
}
//ffmpegPlayer.libSetSurface(null);
}catch (Exception e){
}
return true;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
if(this.surface !=null){
this.surface.release();
this.surface=null;
this.surface=new Surface(surface);
}
}
#Override
public void onMatrixChanged(Matrix matrix, RectF rectF) {
float maxMovement = (rectF.width() - surfaceView.getWidth());
float middle = surfaceView.getWidth() * 0.5f + surfaceView.getLeft();
float currentMiddle = rectF.width() * 0.5f + rectF.left;
float angle=(-(int) ((currentMiddle - middle) * 100 / maxMovement));
Log.d("ANURAN",angle+"");
angleView.setCurrentProgress((int)angle);
}
// public class PlayVideo extends AsyncTask<Void,Void,Void> {
//
// #Override
// protected Void doInBackground(Void... voids) {
// try{
// isInitialized=(FFMPEGPlayer.libInit(url)==0);
// }catch (Exception e){
// e.printStackTrace();
// }
// return null;
// }
//
// #Override
// protected void onPostExecute(Void aVoid) {
// super.onPostExecute(aVoid);
// postInit();
// this.cancel(true);
// }
// }
}
My game crashes whenever I try to open it. It gives me this message in my GameView: Custom view GameView is missing constructor used by tools: (Context) or (Context,AttributeSet) or (Context,AttributeSet,int)
I tried all three different constructors, I've tried a few constructors at the same time and even though the message sometimes goes away my app still crashes when I try to open it. I've been at it for three days, searched all over but could not find an answer.
Here's my MainActivity.java code:
import android.content.Intent;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends ActionBarActivity implements View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Button buttonPlay =(Button)findViewById(R.id.buttonPlay);
buttonPlay.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Intent i = new Intent(this, GameActivity.class);
startActivity(i);
finish();
}
}
Here's my GameView.java code:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GameView extends SurfaceView implements Runnable{
volatile boolean playing;
Thread gameThread = null;
//Game objects
private PlayerShip player;
// For drawing
private Paint paint;
private Canvas canvas;
private SurfaceHolder ourHolder;
GameView(Context context, int x, int y) {
super(context);
ourHolder = getHolder();
paint = new Paint();
player = new PlayerShip(context, x, y );
}
#Override
public void run() {
while (playing) {
update();
draw();
control();
}
}
private void update(){
}
private void draw(){
player.update();
if (ourHolder.getSurface().isValid()) {
canvas = ourHolder.lockCanvas();
canvas.drawColor(Color.argb(255, 0, 0, 0));
canvas.drawBitmap(
player.getBitmap(),
player.getX(),
player.getY(),
paint );
ourHolder.unlockCanvasAndPost(canvas);
}
}
private void control(){
try {
gameThread.sleep(17);
} catch (InterruptedException e) {
}
}
public void pause() {
playing = false;
try {
gameThread.join();
} catch (InterruptedException e) {
}
}
public void resume() {
playing = true;
gameThread = new Thread(this);
gameThread.start();
}
#Override
public boolean onTouchEvent(MotionEvent motionEvent) {
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_UP:
player.stopBoosting();
break;
case MotionEvent.ACTION_DOWN:
player.setBoosting();
break;
}
return true;
}
}
GameActivity.java:
import android.graphics.Point;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.ActionBarActivity;
import android.view.Display;
public class GameActivity extends ActionBarActivity {
private GameView gameView;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get a Display object to access screen details
Display display = getWindowManager().getDefaultDisplay();
// Load the resolution into a Point object
Point size = new Point();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2){
display.getSize(size);
}else{
size.x = display.getWidth();
size.y = display.getHeight();
}
//overrideGetSize(display, size);
gameView = new GameView(this, size.x, size.y);
setContentView(gameView);
}
#Override
protected void onPause() {
super.onPause();
gameView.pause();
}
#Override
protected void onResume() {
super.onResume();
gameView.resume();
}
}
PlayerShip.java code:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
public class PlayerShip {
private final int GRAVITY = -12;
// Stop ship leaving the screen
private int maxY;
private int minY;
//Limit the bounds of the ship's speed
private final int MIN_SPEED = 1;
private final int MAX_SPEED = 20;
private boolean boosting;
private Bitmap bitmap;
private int x, y;
private int speed = 0;
public PlayerShip(Context context, int screenX, int screenY) {
maxY = screenY - bitmap.getHeight();
minY = 0;
boosting = false;
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.ship);
this.x = 50;
this.y = 50;
speed = 1;
}
public void update() {
if (boosting) {
speed += 2;
} else {
speed -= 5;
}
// Constrain top speed
if (speed > MAX_SPEED) {
speed = MAX_SPEED;
}
// Never stop completely
if (speed < MIN_SPEED) {
speed = MIN_SPEED;
}
// move the ship up or down
y -= speed + GRAVITY;
// But don't let ship stray off screen
if (y < minY) {
y = minY;
}
if (y > maxY) { y = maxY;
}
}
//Getters
public Bitmap getBitmap() {
return bitmap;
}
public int getSpeed() {
return speed;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setBoosting() { boosting = true;
}
public void stopBoosting() { boosting = false;
}
}
I have a hunch that the problem could be caused by the x and y in your constructor. Just to experiment, try dropping the x and y and just set those values as constants, then implement all three default view constructors.
public class GameView extends SurfaceView implements Runnable{
...
GameView(Context context) {
super(context);
init(context);
}
GameView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
GameView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
int x = 500;
int y = 500;
ourHolder = getHolder();
paint = new Paint();
player = new PlayerShip(context, x, y);
}
...
I am working on an android app and am trying to figure out how to get a popup confirmation window to display with confirm and cancel buttons when a button is pressed.
Here is the creation of the alert.
final AlertDialog.Builder alertBuilder = new AlertDialog.Builder(activity);
alertBuilder.setTitle("Your Title");
alertBuilder.setMessage("Your Messages");
alertBuilder.setPositiveButton("Confirm", new OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Do something with value!
}
});
alertBuilder.setNegativeButton("Cancel", new OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Canceled.
}
});
Here is the call to show.
Sprite p2 = new Sprite(goldMult, 25, 450, WIDTH, HEIGHT,
resourceManager.spriteRegion, vbom) {
/**
* #see org.andengine.entity.shape.Shape#onAreaTouched(org.andengine.input.touch.TouchEvent, float, float)
*/
#Override
public boolean onAreaTouched(final TouchEvent sceneTouchEvent, final float touchAreaLocalX,
final float touchAreaLocalY) {
AlertDialog alert = alertBuilder.create();
alert.show();
I am getting this exception:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
I saw a post with a similar issue here
However I am confused on how to implement this with my onAreaClicked event.
Thanks for any help in advanced
andengine uses opengl so you might want to create a handler to execute your dialog on the opengl thread
public Handler handler;
then
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
AlertDialog alert = alertBuilder.create();
alert.show();
break;
}
}};
then to use it
handler.sendMessage(Message.obtain(handler, 0));
something along those lines
EDIT: class using handler for looper prepare opengl
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.IntBuffer;
import java.util.List;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import com.facebook.android.AsyncFacebookRunner;
import com.facebook.android.AsyncFacebookRunner.RequestListener;
import com.facebook.android.DialogError;
import com.facebook.android.Facebook;
import com.facebook.android.FacebookError;
import com.facebook.android.Facebook.DialogListener;
import pic.puzzle.framework.Audio;
import pic.puzzle.framework.FileIO;
import pic.puzzle.framework.Game;
import pic.puzzle.framework.Graphics;
import pic.puzzle.framework.Input;
import pic.puzzle.framework.Screen;
import pic.puzzle.picturepuzzle.GameOverScreen;
import pic.puzzle.picturepuzzle.GameOverScreenCustom;
import pic.puzzle.picturepuzzle.PicturePuzzleScreen;
import pic.puzzle.picturepuzzle.PuzzleScreen;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.net.Uri;
import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
public abstract class GLGame extends Activity implements Game, Renderer {
enum GLGameState {
Initialized,
Running,
Paused,
Finished,
Idle
}
GLSurfaceView glView;
GLGraphics glGraphics;
Audio audio;
Input input;
FileIO fileIO;
Screen screen;
GLGameState state = GLGameState.Initialized;
Object stateChanged = new Object();
long startTime = System.nanoTime();
WakeLock wakeLock;
public static Bitmap lastscreenshot;
public static boolean screenshot = false,finish = false;
public static int width, height;
public static Handler handler;
public static boolean share = false;
String APP_ID = ("567944629883125");
public Facebook fb;
public byte[] data;
public static int custom = 0;
public Uri uri;
String here;
#SuppressLint("HandlerLeak")
#SuppressWarnings("deprecation")
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
glView = new GLSurfaceView(this);
glView.setEGLConfigChooser(8 , 8, 8, 8, 16, 0);
glView.setRenderer(this);
setContentView(glView);
fb = new Facebook(APP_ID);
glGraphics = new GLGraphics(glView);
fileIO = new AndroidFileIO(getAssets());
audio = new AndroidAudio(this);
input = new AndroidInput(this, glView, 1, 1);
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "GLGame");
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
if(custom == 0)
uri = GameOverScreen.pngUri;
else if(custom == 1)
uri = GameOverScreenCustom.pngUri;
if(custom == 0){
here = "Moves: " + GameOverScreen.moves + " " + "Time: " + GameOverScreen.time;}
else if(custom == 1){
here = "Moves: " + GameOverScreenCustom.moves + " " + "Time: " + GameOverScreenCustom.time;}
Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(android.content.Intent.EXTRA_TEXT,
here);
shareIntent.setType("image/png");
shareIntent.putExtra(android.content.Intent.EXTRA_STREAM,
uri); //Share the image on Facebook
PackageManager pm = getApplicationContext().getPackageManager();
List<ResolveInfo> activityList = pm.queryIntentActivities(
shareIntent, 0);
for (final ResolveInfo app : activityList) {
if ((app.activityInfo.name).contains("facebook")) {
final ActivityInfo activity = app.activityInfo;
final ComponentName name = new ComponentName(
activity.applicationInfo.packageName,
activity.name);
shareIntent.addCategory(Intent.CATEGORY_LAUNCHER);
shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
shareIntent.setComponent(name);
startActivity(shareIntent);
break;
}
}
}
}
};
}
public void onResume() {
super.onResume();
glView.onResume();
wakeLock.acquire();
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
glGraphics.setGL(gl);
synchronized(stateChanged) {
if(state == GLGameState.Initialized)
screen = getStartScreen();
state = GLGameState.Running;
screen.resume();
startTime = System.nanoTime();
}
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLGame.width = width;
GLGame.height = height;
}
#Override
public void onDrawFrame(GL10 gl) {
GLGameState state = null;
if(finish){
finish = false;
finish();
}
if(share) {
share = false;
handler.sendMessage(Message.obtain(handler, 0));
}
synchronized(stateChanged) {
state = this.state;
}
if(state == GLGameState.Running) {
float deltaTime = (System.nanoTime()-startTime) / 1000000000.0f;
startTime = System.nanoTime();
screen.update(deltaTime);
screen.present(deltaTime);
if(screenshot){
lastscreenshot = SavePixels(0,0,width,height,gl);
lastscreenshot = Bitmap.createScaledBitmap(lastscreenshot, 320, 480, true);
screenshot = false;
}
}
if(state == GLGameState.Paused) {
screen.pause();
synchronized(stateChanged) {
this.state = GLGameState.Idle;
stateChanged.notifyAll();
}
}
if(state == GLGameState.Finished) {
screen.pause();
screen.dispose();
synchronized(stateChanged) {
this.state = GLGameState.Idle;
stateChanged.notifyAll();
}
}
}
#Override
public void onPause() {
synchronized(stateChanged) {
if(isFinishing())
state = GLGameState.Finished;
else
state = GLGameState.Paused;
while(true) {
try {
stateChanged.wait();
break;
} catch(InterruptedException e) {
}
}
}
wakeLock.release();
glView.onPause();
super.onPause();
}
#Override
public void onDestroy(){
if(lastscreenshot != null)
lastscreenshot.recycle();
if(PicturePuzzleScreen.pic != null)
PicturePuzzleScreen.pic.recycle();
if(GameOverScreen.finalbitmap != null)
GameOverScreen.finalbitmap.recycle();
if(GameOverScreenCustom.finalbitmap != null)
GameOverScreenCustom.finalbitmap.recycle();
System.gc();
super.onDestroy();
}
public static Bitmap SavePixels(int x, int y, int w, int h, GL10 gl)
{
int b[]=new int[w*(y+h)];
int bt[]=new int[w*h];
IntBuffer ib=IntBuffer.wrap(b);
ib.position(0);
gl.glReadPixels(x, 0, w, y+h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, ib);
for(int i=0, k=0; i<h; i++, k++)
{//remember, that OpenGL bitmap is incompatible with Android bitmap
//and so, some correction need.
for(int j=0; j<w; j++)
{
int pix=b[i*w+j];
int pb=(pix>>16)&0xff;
int pr=(pix<<16)&0x00ff0000;
int pix1=(pix&0xff00ff00) | pr | pb;
bt[(h-k-1)*w+j]=pix1;
}
}
Bitmap sb=Bitmap.createBitmap(bt, w, h, Bitmap.Config.RGB_565);
return sb;
}
public GLGraphics getGLGraphics() {
return glGraphics;
}
#Override
public Input getInput() {
return input;
}
#Override
public FileIO getFileIO() {
return fileIO;
}
#Override
public Graphics getGraphics() {
throw new IllegalStateException("We are using OpenGL!");
}
#Override
public Audio getAudio() {
return audio;
}
#Override
public void setScreen(Screen screen) {
if (screen == null)
throw new IllegalArgumentException("Screen must not be null");
this.screen.pause();
this.screen.dispose();
screen.resume();
screen.update(0);
this.screen = screen;
}
#Override
public Screen getCurrentScreen() {
return screen;
}
#SuppressWarnings("deprecation")
#Override
protected void onActivityResult(int requestCode,int resultCode,Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
fb.authorizeCallback(requestCode, resultCode, data);
}
}
I figured out the answer by wrapping the Alert in a new thread
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
AlertDialog.Builder alert = new AlertDialog.Builder(activity);
alert.setTitle("");
alert.setMessage("");
alert.setPositiveButton("Buy", new OnClickListener() {
#Override
public void onClick(DialogInterface arg0, int arg1) {
}
});
alert.setNegativeButton("Cancel", new OnClickListener() {
#Override
public void onClick(DialogInterface arg0, int arg1) {
}
});
alert.show();
}
});
I am trying to draw a background image in my android app. However when I try to draw it as a bitmap it says the file is not found. Can you use images from custom folders created in your project directory?
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MainGamePanel extends SurfaceView implements SurfaceHolder.Callback {
Bitmap BackgroundImage;
private static final String TAG = MainGamePanel.class.getSimpleName();
private MainThread thread;
public MainGamePanel(Context context) {
super(context);
// adding the callback (this) to the surface holder to intercept events
getHolder().addCallback(this);
// creating game thread
thread = new MainThread(getHolder(), this);
// make the GmaePanel focusable so it can handle events
setFocusable(true);
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder arg0) {
thread.setRunning(true);
thread.start();
Background b1 = new Background();
BackgroundImage = b1.loadBackgroundImage();
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
Log.d(TAG, "Surface is being destroyed");
boolean retry = true;
while(retry){
try{
thread.join();
retry = false;
} catch (InterruptedException e) {
// try again to shutdown thread
}
}
Log.d(TAG, "Thread was shut down cleanly");
}
#Override
public boolean onTouchEvent(MotionEvent event){
return super.onTouchEvent(event);
}
#Override
protected void onDraw(Canvas canvas){
canvas.drawBitmap(BackgroundImage, 0, 0, null);
}
}
------Background Class------
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
public class Background {
private String imageLoc;
public Background(){
}
public String getImageLoc() {
return imageLoc;
}
public void setImageLoc(String imageLoc) {
this.imageLoc = imageLoc;
}
public Bitmap loadBackgroundImage(){
Bitmap background = BitmapFactory.decodeFile("/Users/Justin/Documents/Project_WinterGalaxy/AndroidGalaxy/images/Background.png");
return background;
}
}
The way to show an image in your code is: put it in the relevant drawable folder and then load it like this:
Bitmap background = BitmapFactory.decodeResource(getResources(), R.drawable.Background);
My code get different behavior when the application runs on Android 2.2 and Android 3.0, code built for android 2.2 and provides no build errors in Eclipse. The Android 2.2 does not seem OnCompletionListener work as expected. Am I doing something wrong or is there any difference between Android 2.2 and 3.0 regarding OnCompletionListener.
My sample code is from http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/media/MediaPlayerDemo_Video.html
import android.app.Activity;
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.media.MediaPlayer.OnVideoSizeChangedListener;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import android.view.WindowManager;
public class MediaPlayerActivity extends Activity implements OnBufferingUpdateListener, OnCompletionListener, OnPreparedListener, OnVideoSizeChangedListener, SurfaceHolder.Callback {
private final String TAG = "MediaPlayer";
private SurfaceView m_preview;
private SurfaceHolder m_holder;
private Bundle m_extras;
private String m_path;
private MediaPlayer m_mediaPlayer;
private int m_videoWidht;
private int m_videoHeight;
private boolean m_isVideoReadyToPlay;
private boolean m_isVideoSizeKnown;
private static final int LOCAL_VIDEO = 1;
private static final int STREAM_VIDEO = 2;
private static final String MEDIA = "media";
private static final String FILE = "/mnt/sdcard/file1.avi";
private WakeLock m_keepscreen;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "MediaPlayer::onCreate");
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.videoplayer);
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
m_keepscreen = pm.newWakeLock( PowerManager.FULL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE | PowerManager.ACQUIRE_CAUSES_WAKEUP,"MediaPlayerActivity");
m_preview = (SurfaceView) findViewById(R.id.surface);
m_holder = m_preview.getHolder();
m_holder.addCallback(this);
m_holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
m_extras = getIntent().getExtras();
m_keepscreen.acquire();
}
private void playVideo(Integer media){
doCleanUp();
try{
switch (media){
case LOCAL_VIDEO :
m_path = FILE;
Log.i(TAG, "File: "+FILE);
if(m_path == ""){
//
}
break;
case STREAM_VIDEO:
Log.i(TAG, "PlayVideo, cant stream video yet");
break;
}
m_mediaPlayer = new MediaPlayer();
m_mediaPlayer.setDataSource(m_path);
m_mediaPlayer.setDisplay(m_holder);
m_mediaPlayer.prepare();
m_mediaPlayer.setOnBufferingUpdateListener(this);
m_mediaPlayer.setOnPreparedListener(this);
m_mediaPlayer.setOnCompletionListener(this);
/*
m_mediaPlayer.setOnCompletionListener(new OnCompletionListener(){
public void onCompletion(MediaPlayer mp) {
Log.i(TAG, "MediaPlayer::onCompletion");
startVideoPlayback();
}
});
*/
m_mediaPlayer.setOnVideoSizeChangedListener(this);
m_mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}catch (Exception e){
Log.i(TAG, "Error: "+e.getMessage());
}
}
private void doCleanUp() {
m_videoWidht = 0;
m_videoHeight = 0;
m_isVideoReadyToPlay = false;
m_isVideoSizeKnown = false;
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
Log.i(TAG, "MediaPlayer::surfaceChanged");
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Log.i(TAG, "MediaPlayer::surfaceCreated");
playVideo(1);
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.i(TAG, "MediaPlayer::surfaceDestroyed");
}
#Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
Log.i(TAG, "MediaPlayer::videoSizeChanged");
if( width == 0 || height == 0 ){
Log.i(TAG, "invalid video with("+width+")or height ("+height+")");
}
m_isVideoSizeKnown = true;
m_videoWidht = width;
m_videoHeight = height;
if(m_isVideoReadyToPlay && m_isVideoSizeKnown){
startVideoPlayback();
}
}
private void startVideoPlayback() {
Log.i(TAG, "StartVideoPlayback");
m_holder.setFixedSize(m_videoWidht, m_videoHeight);
m_mediaPlayer.start();
}
#Override
public void onPrepared(MediaPlayer mp) {
Log.i(TAG, "MediaPlayer::onPrepared");
m_isVideoReadyToPlay = true;
if(m_isVideoReadyToPlay && m_isVideoSizeKnown){
startVideoPlayback();
}
}
#Override
public void onCompletion(MediaPlayer mp) {
//android 2.2 never get here
Log.i(TAG, "MediaPlayer::onCompletion");
startVideoPlayback();
}
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
Log.i(TAG, "MediaPlayer::onBufferingUpdate: "+percent+" %");
}
#Override
protected void onPause() {
super.onPause();
releaseMediaPlayer();
doCleanUp();
}
#Override
protected void onDestroy() {
super.onDestroy();
releaseMediaPlayer();
doCleanUp();
}
private void releaseMediaPlayer() {
if (m_mediaPlayer != null) {
m_mediaPlayer.release();
m_mediaPlayer = null;
m_keepscreen.release();
}
}
}