application stops working when pressing back or home key? - java

I have 3 classes, class GameThread that extend thread, class Main that extend Activity, class GameView that extend surfaceview implement surfaceHolder.onCallback:
public class Main extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("oncreate","ONcreate");
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.gameloopxml);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Class GameThread:
public class GameThread extends Thread {
GameView gameview;
SurfaceHolder surfaceHolder;
public boolean running;
public GameThread(SurfaceHolder surfaceHolder,GameView gameview){
this.gameview=gameview;
running=false;
this.surfaceHolder=surfaceHolder;
}
#Override
public void run() {
Canvas c;
//super.run();
while(running){
c=null;
try{
c=surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
if(c!=null){
c.drawColor(Color.BLACK);
gameview.draw(c);
gameview.update();
}
}
}finally{
if(c!=null){
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
Class GameView:
public class GameView extends SurfaceView implements SurfaceHolder.Callback{
GameThread gamethread;
Paint p=new Paint();
int x,y;
Bitmap bitmap;
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
Log.i("surface", "constructor");
bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
//super(context);
p.setColor(Color.RED);
//add the callback this in order to intercept events
getHolder().addCallback(this);
//create the gameloop
//make it foccusable so it can handle events
setFocusable(true);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
Log.i("surface", "changed");
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Log.i("surface", "created");
gamethread=new GameThread(getHolder(),this);
gamethread.running=true;
gamethread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.i("surface", "destroyed");
boolean tryagain=false;
while(tryagain){
try {
gamethread.join();//destroy the thread
tryagain=false;
gamethread.running=false;
} catch (InterruptedException e) {
//try again shutting down the thread
}
}
}
public void draw(Canvas c) {
c.drawRect(x, y, x+80, y+80, p);
}
public void update(){
x++;
y++;
}
}
Everything works fine in my code except that whenever I press the back or home key I am getting a Nullpointer exception in the logcat.

Related

How to update data to an object created from a custom view class ,so that it can be drawn on custom view?

My application requires to post data to a custom view and redraw the view according to sent data from MainActivity.
Here are sample code.
Custom view->
public class custom_view extends View {
private simple_line line;
public custom_view(Context context) {
super(context);
line=new simple_line(0);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
line.draw_line(canvas);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(),getMeasuredHeight());
}
private class simple_line{
private float x_val;
private Paint mpaint;
public simple_line(float val){
x_val=val;
mpaint=new Paint();
mpaint.setColor(Color.RED);
mpaint.setStyle(Paint.Style.STROKE);
mpaint.setStrokeWidth(10);
}
public float getX_val() {
return x_val;
}
public void setX_val(float x_val) {
this.x_val = x_val;
invalidate();
}
public void draw_line(Canvas canvas){
Path mpath=new Path();
mpath.moveTo(getWidth()/2+x_val,0);
mpath.lineTo(getWidth()/2+x_val,getHeight());
mpath.close();
canvas.drawPath(mpath,mpaint);
}
}
public void update_xval(float val){
line.setX_val(val);
}
}
Here is Main activity->
public class MainActivity extends AppCompatActivity{
private Button button;
private custom_view myview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=(Button)findViewById(R.id.mybutton);
myview=(custom_view)findViewById(R.id.myview);
myview=new custom_view(this);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myview.update_xval(100);
}
});
}
}
I am unable to update x_val when button is pressed.Where am I going wrong.What needs to be done to update x_val?
there is an issue in draw_line(Canvas canvas) function. you are not calling this function in custom_view. you need to invalidate() after draw_line(Canvas canvas)called.

How to animate TextureView?

I am trying to fade in a TextureView but for some reason its not animating. It just simply pops in the video, no fade at all and i dont really know why that is because after some research i have found that TextureView can be animated normally.
Here is my code, i hope you guys can give me a pointer in the right direction.
PS, i have left out all irrelevant code that does not concern itself with the textureview and the animation.
public class MainActivity extends AppCompatActivity implements MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener
{
private static final String TAG = MainActivity.class.getSimpleName();
private MediaPlayer mediaPlayer1;
private ArrayList<Uri> videoUris = new ArrayList<>();
private int current_video_index = 0;
private TextureView textureView;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textureView = (TextureView) findViewById(R.id.textureView);
mediaPlayer1 = new MediaPlayer();
mediaPlayer1.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer1.setOnPreparedListener(this);
mediaPlayer1.setOnCompletionListener(this);
initVideoUris();
initNewVideo();
}
private void startVideo(final Uri uri)
{
textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener()
{
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height)
{
try {
mediaPlayer1.setDataSource(MainActivity.this, uri);
mediaPlayer1.setSurface(new Surface(surface));
mediaPlayer1.setOnCompletionListener(MainActivity.this);
mediaPlayer1.setOnPreparedListener(MainActivity.this);
mediaPlayer1.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer1.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height)
{
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface)
{
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface)
{
}
});
}
#Override
public void onPrepared(MediaPlayer mp)
{
mp.start();
fadeInView(textureView);
}
#Override
public void onCompletion(MediaPlayer mp)
{
if (!moreVideosAvailable())
{
finish();
}
}
private boolean moreVideosAvailable()
{
return current_video_index < videoUris.size();
}
private void fadeInView(View view)
{
view.setAlpha(0f);
view.setVisibility(View.VISIBLE);
view.animate().alpha(1f).setDuration(2000).setListener(null).start();
}
}
I solved it by making a videoPlayerFragment that uses TextureView as the surface for displaying the video. Then simply animate the whole fragment instead of the textureView.

android - call method in view from activity

I am working on a 2d game and I'm trying to make the view where I draw and update everything tell the activity that contains it that the game ended and display a pop-up on the screen. The problem is that I don't know how to access the method in the activity from the view because they work on different threads.
The code looks more or less like this and I want to access the method displayFrame() from the view class. The method in the real code does more operations with other textViews etc. that only the activity has access to.
public class MainActivity extends Activity{
private MyView myView;
RelativeLayout finalFrame;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myView = new MyView(this.getApplicationContext());
this.setContentView(myView);
finalFrame = (RelativeLayout) findViewById(R.id.framefinal);
}
private void displayFrame(){
this.finalFrame.setVisibility(View.VISIBLE);
}
}
public class MyView extends SurfaceView implements SurfaceHolder.Callback{
private MyThread myThread;
private boolean finished = false;
public MyView(Context context) {
super(context);
getHolder().addCallback(this);
this.myThread = new MyThread(getHolder(), this);
this.myThread.setRunning(true);
}
public void update() {
this.finished = someMethod();
if(this.finished){
MainActivity.displayFrame();
}
}
public void draw(Canvas canvas){
//draw something
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
public class MyThread extends Thread{
private MyView myView;
private SurfaceHolder surfaceHolder;
private boolean running = false;
private static Canvas canvas;
public MyThread(SurfaceHolder surfaceHolder, MyView myView){
super();
this.surfaceHolder = surfaceHolder;
this.myView = myView;
}
#Override
public void run(){
while(running){
canvas = null;
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
this.myView.update();
this.myView.draw(canvas);
}
} catch (Exception e) {e.printStackTrace();}
finally{
if(canvas!=null)
{
try {
surfaceHolder.unlockCanvasAndPost(canvas);
}
catch(Exception e){e.printStackTrace();}
}
}
}
}
public void setRunning(boolean running){
this.running = running;
}
}
The easiest way to do that is to define a listener interface in your view and make the activity implement it. Then you can notify the activity that your game has ended and execute the appropriate logic.
public class MyView extends SurfaceView implements SurfaceHolder.Callback {
// your other fields
private GameListener mGameListener;
public void setGameListener(GameListener gameListener) {
mGameListener = gameListener;
}
public void update() {
// your logic
if (mGameListener != null) {
// calling onGameEnd on the main thread
post(new Runnable() {
public void run() {
mGameListener.onGameEnd();
}
});
}
}
// rest of your class as it is
public interface GameListener {
void onGameEnded();
}
}
public class MainActivity extends Activity implements GameListener {
// the rest of your class
public void onGameEnded() {
// call the method you need
}
}
public class MyView extends SurfaceView implements SurfaceHolder.Callback{
private MyThread myThread;
private boolean finished = false;
private Context context;
public MyView(Context context) {
super(context);
this.context=context;
getHolder().addCallback(this);
this.myThread = new MyThread(getHolder(), this);
this.myThread.setRunning(true);
}
runOnUiThread(new Runnable(){
#Override
public void run(){
update();
}
});
public void update() {
this.finished = someMethod();
if(this.finished){
MainActivity mainActivity = (MainActivity) context;
mainActivity.displayFrame();
}
}
public void draw(Canvas canvas){
//draw something
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
Can you try this

Java Android, attach guesture listener

I wrote Gesture Detector class and no try to add the gesture listener, it works fine when i call it in the onCreate() function for the activity_main view but i can't attach it to the invisible view with i create by button click.. Here is my code,
I receive no errors, it just don't listen, i can also set a onTouchListener() in the invisibleView class..
main
public class MainActivity extends Activity {
String TAG = "myTAG";
SocketClass mySocketClass;
View viewToWatch;
InvisibleView myInvisibleView;
Context myContext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
savedInstanceState = new Bundle();
myInvisibleView = new InvisibleView();
/*
-----------------------------------------------------
this works, when i add the listener to the main view:
-----------------------------------------------------
viewToWatch= (View) findViewById(R.id.mainViewId);
viewToWatch.setOnTouchListener(new ClassGesturesDetection() {
public void returnSingleTapUp() {
Log.d ("Gesture from main View", "single tab");
}
});
-----------------------------------------------------
*/
}
public void startApp(View activity_main_view){
myInvisibleView.onCreate(this.getApplicationContext());
putOnTochListenerToInvsibleView();
}
public void putOnTochListenerToInvsibleView( ) {
/*
-----------------------------------------------------
there i want to add the listener:
-----------------------------------------------------
*/
setContentView(R.layout.invisibleviewxml);
viewToWatch= (View) findViewById(R.id.invisibleViewId);
viewToWatch.setOnTouchListener(new ClassGesturesDetection() {
public void returnSingleTapUp() {
Log.d ("Gesture from transparent view", "single tab");
}
});
}
}
here the class where i create the system overlay view:
public class InvisibleView extends Service {
View myView;
#Override
public IBinder onBind(Intent intent) {
return null;
}
public void onCreate(Context myContext) {
super.onCreate();
LayoutInflater inflater = (LayoutInflater) myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
myView = new View(myContext);
myView = inflater.inflate(R.layout.invisibleviewxml, null);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
WindowManager wm = (WindowManager) myContext.getSystemService(WINDOW_SERVICE);
wm.addView(myView, params);
/*
-----------------------------------------------------
this also works,the system overlay catches clicks
-----------------------------------------------------
myView.setOnTouchListener( new OnTouchListener() {
#Override
public boolean onTouch(View inviView, MotionEvent event) {
Log.d("Gesture", "simple touch from InvisibleView Class");
return true;
}
});
-----------------------------------------------------
this does not work
-----------------------------------------------------
myView.setOnTouchListener(new ClassGesturesDetection() {
public void returnSingleTapUp() {
Log.d ("Gesture from transparent", "single tab");
}
});
----------------------------------------------------- */
}
#Override
public void onDestroy() {
super.onDestroy();
if(myView != null)
{
((WindowManager) getSystemService(WINDOW_SERVICE)).removeView(myView);
myView = null;
}
}
}
here the my Class of Gesture Dedection:
public class ClassGesturesDetection implements OnTouchListener {
#SuppressWarnings("deprecation")
private final GestureDetector gestureDetector = new GestureDetector(new GestureListener());
public boolean onTouch(final View view, final MotionEvent motionEvent) {
return gestureDetector.onTouchEvent(motionEvent);
}
private final class GestureListener extends SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
#Override
public boolean onDown(MotionEvent e) {
//Log.d("class Gesture", "on Down");
return true;
}
#Override
public void onLongPress(MotionEvent e) {
returnOnLongPress();
}
#Override
public boolean onSingleTapUp(MotionEvent e) {
returnSingleTapUp();
return false;
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight();
} else {
onSwipeLeft();
}
}
} else {
if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeBottom();
} else {
onSwipeTop();
}
}
}
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
}
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
public void onSwipeTop() {
}
public void onSwipeBottom() {
}
public void returnSingleTapUp() {
}
public void returnOnLongPress() {
}
}
you must add this permission
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
You can follow this
I had answered there for your question

How to call a method of another class in one class

I want to call MyView.circle() method when I click on menu Circle but when I'm clicking on menu it is throwing a NullPointerException, which means that the object is not initialized as I expected.
Here is my code. Where am I going wrong?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyView(this));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
menu.add(0,1,1,"Circle");
menu.add(0,1,2,"Rect");
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch(item.getItemId())
{
case 1:
MyView.circle();
break;
}
return super.onOptionsItemSelected(item);
}
public static class MyView extends View {
private Context context;
static Canvas can=null;
public MyView(Context c) {
super(c);
context=c;
}
#Override
protected void onDraw(Canvas canvas) {
mPaint=new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLUE);
mPaint.setAntiAlias(true);
//circle(canvas);
}
public static void circle() {
// TODO Auto-generated method stub
can.drawCircle(50, 50, 50, mPaint);
}
}
}
public void static circle(c) {
needs to be changed to
public void static circle(Canvas c) {
Might I recommend spending some time learning Java before writing Android apps?

Categories