I have been trying for a while to implement a Game Thread to utilise a loop to implement logic. I posted a question here not long ago, I hope no one minds the follow up.
I have managed to scrape together this code from my research:
public class GameView extends SurfaceView implements SurfaceHolder.Callback
{
class GameThread extends Thread
{
//states
public static final int STATE_LOSE = 1;
public static final int STATE_PAUSE = 2;
public static final int STATE_READY = 3;
public static final int STATE_RUNNING = 4;
private Paint m_paint;
//canvas dimensions
private int m_canvasWidth;
private int m_canvasHeight;
private long m_lastTime;
private boolean m_run = false;
private int m_mode;
public ImageView ship;
RelativeLayout.LayoutParams shipParams;
// Handle to the surface manager
private SurfaceHolder m_surfaceHolder;
public GameThread(SurfaceHolder surfaceHolder, Context context, Handler handler)
{
m_surfaceHolder = surfaceHolder;
}
//Initialise the game
public void doStart()
{
synchronized (m_surfaceHolder)
{
resetGame();
m_lastTime = System.currentTimeMillis() + 100;
setState(STATE_RUNNING);
ship = (ImageView) findViewById(R.id.imageView1);
shipParams = (RelativeLayout.LayoutParams)ship.getLayoutParams();
}
}
public void pause()
{
synchronized (m_surfaceHolder)
{
if (m_mode == STATE_RUNNING)
setState(STATE_PAUSE);
}
}
#Override
public void run()
{
while (m_run)
{
Canvas c = null;
try
{
c = m_surfaceHolder.lockCanvas(null);
synchronized (m_surfaceHolder)
{
if (m_mode == STATE_RUNNING)
{
updateGame();
}
doDraw(c);
}
}
catch(Exception e){}
finally
{
if (c != null)
{
m_surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
public void setRunning(boolean b)
{
m_run = b;
}
public void setState(int mode)
{
synchronized (m_surfaceHolder)
{
setState(mode, null);
}
}
public void setState(int mode, CharSequence message)
{
synchronized (m_surfaceHolder)
{
m_mode = mode;
}
}
public void setPlayers(boolean onePlayer)
{
}
public void setSurfaceSize(int width, int height)
{
synchronized (m_surfaceHolder)
{
m_canvasWidth = width;
m_canvasHeight = height;
}
}
public void unpause()
{
synchronized (m_surfaceHolder)
{
m_lastTime = System.currentTimeMillis() + 100;
}
setState(STATE_RUNNING);
}
private void doDraw(Canvas canvas)
{
canvas.drawARGB(255, 0, 0, 0);
}
private void updateGame()
{
long now = System.currentTimeMillis();
if (m_lastTime > now)
return;
double elapsed = (now - m_lastTime) / 1000.0;
m_lastTime = now;
System.out.print("HELLO WORLD");
shipParams.topMargin++;
ship.setLayoutParams(shipParams);
}
private boolean collided(Rect rectangle)
{
return false;
}
public boolean foundWinner()
{
return false;
}
public void resetGame()
{
}
public void handleInput(MotionEvent event)
{
}
}
private Context m_context;
private GameThread m_thread;
private Handler m_handler;
public GameView(Context context, AttributeSet attrs)
{
super(context, attrs);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
m_handler = new Handler() {
#Override
public void handleMessage(Message m) {
Bundle b = m.getData();
MotionEvent e = b.getParcelable("event");
m_thread.handleInput(e);
}
};
m_thread = new GameThread(holder, context, m_handler);
setFocusable(true);
};
public GameThread getThread()
{
return m_thread;
}
#Override
public void onWindowFocusChanged(boolean hasWindowFocus)
{
if (!hasWindowFocus)
m_thread.pause();
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
m_thread.setSurfaceSize(width, height);
}
public void surfaceCreated(SurfaceHolder holder)
{
if(m_thread.getState() == State.TERMINATED)
{
m_thread = new GameThread(getHolder(), m_context, m_handler);
m_thread.setRunning(true);
m_thread.start();
m_thread.doStart();
}
else
{
m_thread.setRunning(true);
m_thread.start();
}
}
public void surfaceDestroyed(SurfaceHolder holder)
{
boolean retry = true;
m_thread.setRunning(false);
while (retry)
{
try
{
m_thread.join();
retry = false;
}
catch (InterruptedException e)
{
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
return true;
}
}
I am fairly certain that my issue lies here and it is merely a logical one. Everything does seem fine to me, however and I am in need of assistance.
I have attempted to draw an image at line 47 and defined a movement to take place in the update method at line 153. I also have placed a print line for extra debug, but the line doesn't show.
I am stumped.
Any help would be great, thanks.
Here are my other codes, if neccessary:
MainActivity.java
GameSetup.java
game_setup.xml
edit: I should note that I'm not getting any kind of errors within the code, it merely doesn't respond
You are initializing m_run as false,then in the while cycle in the run() method you must have set to true. Change it to true and the thread will work normally.
set m_run to true in your doStart() procedure
Related
I'm creating an animation and this animation must work using a moving object (my object class).
My problem is that when I pause the app the animation starts all over again after I resumed my app . . .
I will use this animation for my 2D game... and here's the code:
The Object Class:
private boolean enabled;
private final Paint paint = new Paint();
public Object() {
stylePaint(paint);
}
public abstract void draw(Canvas var1);
public Paint getPaint() {
return paint;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean bl) {
enabled = bl;
}
public abstract void stylePaint(Paint var1);
The Class that I used which extends my Object Class:
private Point pos;
private Bitmap bitmap;
private Context context;
private int height, width, visibility;
private static int vheight, vwidth;
private static View view;
public static final int
VISIBLE = 255,
INVISIBLE = 0;
public static final int
dirAll = -5,
dirX = -1,
dirY = -2,
ndirAll = -6,
ndirX = -3,
ndirY = -4;
private int speed;
public Actor(int x, int y) {
pos = new Point(x, y);
if(getSyncedView() != null) context = getSyncedView().getContext();
}
public Actor(int x, int y, int w, int h) {
this(x, y);
setDimensions(w, h);
}
public int getWidth() {
return width;
}
public static void syncView(View v) {
view = v;
vheight = v.getHeight();
vwidth = v.getWidth();
}
public static View getSyncedView() {
return view;
}
public void setPadding(int x, int y) {
setDimensions(getX() + x, getY() + y);
}
public void setGravity(Gravity where) { // Gravity is an enum
if(view != null) {
final int
n = vwidth - width,
n2 = vheight - height,
n3 = n / 2,
n4 = n2 / 2;
switch (where) {
case CENTER: {
setGravity(Gravity.CENTER_HORIZONTAL);
setGravity(Gravity.CENTER_VERTICAL);
break;
}
case CENTER_HORIZONTAL: {
setX(n3);
break;
}
case CENTER_VERTICAL: {
setY(n4);
break;
}
case LEFT: {
setX(0);
break;
}
case RIGHT: {
setX(n);
break;
}
case TOP: {
setY(0);
break;
}
case BOTTOM: {
setY(n2);
break;
}
default: {
break;
}
}
}
}
public int getHeight() {
return height;
}
public void setDimensions(int w, int h) {
width = w;
height = h;
}
public Point getPoint() {
return pos;
}
public Rect getRect() {
Rect rect = new Rect();
getRectF().round(rect);
return rect;
}
public RectF getRectF() {
return new RectF(getX(), getY(), getX() + width, getY() + height);
}
public void setPos(int x, int y) {
pos = new Point(x, y);
}
public void setVisibility(int visible) {
getPaint().setAlpha(visible);
}
public int getVisibility() {
return visibility;
}
public void alignTo(PositionedObject target, Gravity where) {
//Aligning this to target
if(view != null) {
int n = target.getX(),
n2 = (target.getWidth() - getWidth()) / 2,
n3 = (target.getWidth() + getWidth()) / 2,
n4 = target.getY(),
n5 = (target.getHeight() - getHeight()) / 2,
n6 = (target.getHeight() + getHeight()) / 2;
switch (where) {
case CENTER: {
setX(n + n2);
setY(n4 + n5);
break;
}
case BOTTOM: {
setX(n + n2);
setY(n4 + n5 + n6);
break;
}
case TOP: {
setX(n + n2);
setY(n4 + n5 - n6);
break;
}
case LEFT: {
setX(n + n2 - n3);
setY(n4 + n5);
break;
}
case RIGHT: {
setX(n + n2 + n3);
setY(n4 + n5);
break;
}
default: break;
}
}
}
public int getX() {
return pos.x;
}
public void setX(int x) {
pos.x = x;
}
public int getY() {
return pos.y;
}
public void setY(int y) {
pos.y = y;
}
public boolean intersect(MovingObject mo) {
return getRect().intersect(mo.getRect());
public int getSpeed() {
return speed;
}
public void move(int where) {
if (isEnabled()) {
switch (where) {
case dirX: {
getPoint().x = getPoint().x + getSpeed();
break;
}
case ndirX: {
getPoint().x = getPoint().x - getSpeed();
break;
}
case dirY: {
getPoint().y = getPoint().y + getSpeed();
break;
}
case ndirY: {
getPoint().y = getPoint().y - getSpeed();
break;
}
case dirAll: {
move(dirX);
move(dirY);
break;
}
case ndirAll: {
move(ndirX);
move(ndirY);
break;
}
}
}
}
public void setSpeed(int sp) {
speed = sp;
}
#Override
public void draw(Canvas canvas) {
canvas.drawBitmap(getBitmap(), getX(), getY(), getPaint());
}
#Override
public void stylePaint(Paint p) {
}
public void setBitmap(Bitmap bm) {
bitmap = bm;
}
public Bitmap getBitmap() {
return bitmap;
}
Bitmap a(Bitmap bm) {
setBitmap(bm);
setDimensions(bm.getWidth(), bm.getHeight());
return getBitmap();
}
public Bitmap createFromAsset(String path) {
try {
return a(BitmapFactory.decodeStream(context.getAssets().open(path)));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public Bitmap createFromRes(int drawable) {
return a(BitmapFactory.decodeResource(context.getResources(), drawable));
}
My SurfaceView:
public SharedPreferences pref;
public SharedPreferences.Editor editor;
private final Paint paint = new Paint();
private BaseThread thread;
private Thread thread2;
private int panelColor;
public Actor cmd, actor, actor2; // The class that extends my object class.
public AbstractPanel(Context context) {
super(context);
init(context);
}
public AbstractPanel(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
void init(Context context) {
SurfaceHolder holder = getHolder();
thread = new BaseThread(holder);
pref = context.getSharedPreferences("Scene", Context.MODE_PRIVATE);
editor = pref.edit();
holder.addCallback(this);
panelColor = Color.BLACK;
}
protected BaseThread getLoop() {
return thread;
}
protected Paint getPaint() {
return paint;
}
#Override
public boolean onKeyDown(int var1, KeyEvent var2) {
return true;
}
public void onStart() {
PositionedObject.syncView(this);
cmd = new Actor(0, 0);
actor = new Actor(0, 0);
actor2 = new Actor(0, 0);
cmd.createFromAsset("cmd.png");
actor.createFromAsset("grandGL.png");
actor2.createFromAsset("presents.png");
actor.setGravity(Gravity.CENTER);
actor2.alignTo(actor, Gravity.BOTTOM);
actor.setVisibility(Actor.INVISIBLE);
actor2.setVisibility(Actor.INVISIBLE);
cmd.setSpeed(1);
cmd.setEnabled(true);
}
public void onTimer() {}
public boolean onTouchEvent(MotionEvent motionEvent) {
return true;
}
public void redrawCanvas(Canvas canvas) {
actor.draw(canvas);
actor2.draw(canvas);
cmd.draw(canvas);
cmd.move(Actor.dirX);
switch (cmd.getX()) {
default : break;
case 25: {
actor.setVisibility(30);
break;
}
case 26: {
actor.setVisibility(60);
break;
}
case 27: {
actor.setVisibility(90);
break;
}
case 28: {
actor.setVisibility(120);
break;
}
case 29: {
actor.setVisibility(150);
break;
}
case 30: {
actor.setVisibility(180);
break;
}
case 31: {
actor.setVisibility(210);
break;
}
case 32: {
actor.setVisibility(240);
break;
}
case 35: {
actor.setVisibility(Actor.VISIBLE);
break;
}
case 60: {
actor2.setVisibility(Actor.VISIBLE);
break;
}
case 130: {
actor.setVisibility(210);
actor2.setVisibility(210);
break;
}
case 132: {
actor.setVisibility(190);
actor2.setVisibility(190);
break;
}
case 134: {
actor.setVisibility(160);
actor2.setVisibility(160);
break;
}
case 136: {
actor.setVisibility(130);
actor2.setVisibility(130);
break;
}
case 138: {
actor.setVisibility(100);
actor2.setVisibility(100);
break;
}
case 140: {
actor.setVisibility(60);
actor2.setVisibility(60);
break;
}
case 142: {
actor.setVisibility(30);
actor2.setVisibility(30);
break;
}
case 146: {
actor.setVisibility(Actor.INVISIBLE);
actor2.setVisibility(Actor.INVISIBLE);
break;
}
}
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
canvas.drawColor(panelColor);
redrawCanvas(canvas);
}
public void setPanelColor(int n) {
panelColor = n;
}
public void startGameLoop() {
thread.setRunning(true);
}
public void stopGameLoop() {
thread.setRunning(false);
}
public void surfaceChanged(SurfaceHolder hol, int n, int w, int h) {
}
public void surfaceCreated(SurfaceHolder holder) {
thread2 = new Thread(thread);
thread2.setPriority(1);
startGameLoop();
thread2.start();
onStart();
}
public void surfaceDestroyed(SurfaceHolder holder) {
stopGameLoop();
}
public class BaseThread implements Runnable {
private SurfaceHolder surHol;
private boolean running;
public BaseThread(SurfaceHolder holder) {
surHol = holder;
}
public void delay(long l) {
try {
Thread.sleep(l);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public boolean isRunning() {
return running;
}
public void setRunning(boolean run) {
synchronized (this) {
running = run;
}
}
#Override
public void run() {
synchronized (surHol) {
delay(800L);
while (isRunning()) {
Canvas canvas = null;
try {
canvas = surHol.lockCanvas();
synchronized (canvas) {
onTimer();
draw(canvas);
}
} catch (Exception e) {
} finally {
if (canvas != null) {
surHol.unlockCanvasAndPost(canvas);
delay(36L);
}
}
}
}
}
I also need simplifications for my codes . . . Thanks in advance for the help . . .
I only accept codes using SurfaceView because this is for my game . . .
SOLVED
Here' s the final code and it's free to copy . . .
I've found out that some onStart() methods must be at the constructor since onStart() method is always called after resuming so I created an onCreate() method to put some codes of onStart() . . .
For LCPanel that extends AbstractPanel that extends SurfaceView:
Actor
cmd,
actor,
actor2;
public LCPanel(Context context) {
super(context);
}
#Override
public boolean onKeyDown(int n, KeyEvent keyEvent) {
return true;
}
#Override
public void onCreate() {
cmd = new Actor(0, 0);
actor = new Actor(0, 0);
actor2 = new Actor(0, 0);
cmd.createFromAsset("cmd.png");
actor.createFromAsset("grandGL.png");
actor2.createFromAsset("presents.png");
}
#Override
public void onStart() {
actor.setGravity(Gravity.CENTER);
actor2.alignTo(actor, Gravity.BOTTOM);
actor.setVisibility(Actor.INVISIBLE);
actor2.setVisibility(Actor.INVISIBLE);
cmd.setSpeed(1);
cmd.setEnabled(true);
}
#Override
public boolean onTouchEvent(MotionEvent motionEvent) {
return true;
}
/* package */ final int a (int n, int n2) {
return (30 * (n - n2)) > 255 ? 255 : 30 * (n - n2); // alpha animator
}
#Override
public void onDraw(Canvas canvas) {
int n = cmd.getX();
actor.draw(canvas);
actor2.draw(canvas);
cmd.draw(canvas);
cmd.move(Actor.dirX);
if (n >= 25 && n <= 38) actor.setVisibility(a(n, 25));
if(n >= 38 && n <= 145) {
actor.setVisibility(Actor.VISIBLE);
if (n >= 74) actor2.setVisibility(Actor.VISIBLE);
}
if (n >= 145 && n <= 162) {
int n3 = 255 - a(n, 145);
actor.setVisibility(n3);
actor2.setVisibility(n3);
actor.shrink();
}
if (n >= 163) {
canvas.drawColor(Color.WHITE);
actor2.draw(canvas);
actor2.createFromAsset("loadin.png");
actor2.setGravity(Gravity.CENTER);
actor2.setVisibility(Actor.VISIBLE);
}
}
Edit some existing AbstractPanel methods:
public AbstractPanel(Context context) {
super(context);
init(context);
}
public AbstractPanel(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
void init(Context context) {
pref = context.getSharedPreferences("Scene", Context.MODE_PRIVATE);
editor = pref.edit();
getHolder().addCallback(this);
Actor.syncView(this);
onCreate();
}
public abstract void onStart();
public abstract void onCreate();
public abstract void onDraw(Canvas canvas);
Edit the thread inside the AbstractClass:
public class BaseThread extends Thread {
private SurfaceHolder surHol;
private boolean running;
public BaseThread(SurfaceHolder holder) {
super();
surHol = holder;
}
public void delay(long l) {
try { sleep(l); } catch (InterruptedException e) {}
}
public void setRunning(boolean run) {
running = run;
}
#Override
public synchronized void run() {
delay(800L);
onStart();
while (true) {
if (!running) break;
Canvas canvas = null;
try {
canvas = surHol.lockCanvas();
synchronized (canvas) {
draw(canvas);
}
} catch (Exception e) {
} finally {
if (canvas != null) {
surHol.unlockCanvasAndPost(canvas);
delay(36L);
}
}
}
}
And done, problem solved..! The animation must work properly as expected . . .
So I am running into a problem with a function I made to slowly change the value of a monitored variable over time that is causing all the java logic to lock up. It doesn't seem to be producing an error or make the application crash so it must be getting stuck in the while loop or something but the logging isn't firing while it is locked so I am just very confused. If anyone can help me figure out how to diagnose what is causing the freezing that would be very much appreciated
EDIT: Turns out the problem was updating the UI from another thread, I manged to get it to crash and got the error and used a CountDownTimer instead of the background thread and now it is working fine. For those curious checkout my GitHub for this project.
Function in question:
public static void changeOverTime(final MonitoredVariable<Integer> tVar, final int tTo, final long tTime, final long tUpdateFreq) {
if (tTime < tUpdateFreq) { Log.e(TAG, "Time must be greater then update freq."); }
if (tVar == null) { Log.e(TAG, "Container cannot be null."); }
else {
final Thread tBackgroundThread = new Thread(new Runnable() {
#Override
public void run() {
float tSteps = tTime / tUpdateFreq; // 2000/100 = 20
float tInterval = (tTo - tVar.get()) / tSteps; // 67-175 = -108/20 = -5.4
float tVal = tVar.get(); //175
while (Math.round(tVal) != tTo) { //67(After 20 Times) != 67 -> FALSE
Debug.Log(TAG, "EQ: " + Math.round(tVal) + "?=" + tTo);
tVal += tInterval; // -5.4 * 20(Times) = -108+175 = 67
tryToSleep(tUpdateFreq); // 100ms * 20(Times) = 2000ms total
tVar.set(Math.round(tVal));
}
}
});
tBackgroundThread.start();
}
}
Supporting Function:
private static void tryToSleep(long tTime) {
try { sleep(tTime); }
catch (InterruptedException e) { e.printStackTrace(); }
}
Monitored Variable Class:
public class MonitoredVariable<Prototype> {
protected Prototype mData;
protected ChangeListener mListener;
public MonitoredVariable(Prototype tData) {
this(tData, null);
}
public MonitoredVariable(Prototype tData, ChangeListener tListener) {
if (tListener != null) setListener(tListener);
mData = tData;
}
public Prototype get() {
return mData;
}
public void set(Prototype tData) {
if (mData != tData) {
mData = tData;
notifyChange();
}
}
public void setListener(ChangeListener tListener) {
mListener = tListener;
}
public ChangeListener getListener() {
return mListener;
}
public void notifyChange() {
if (mListener != null) mListener.onChange();
}
public interface ChangeListener {
void onChange();
}
}
Usage:
public static void init() {
MonitoredVariable.ChangeListener tUpdateBackground = new MonitoredVariable.ChangeListener() {
#Override
public void onChange() { updateBackgroud();
}
};
mTop = new MonitoredVariable[]{
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground)
};
mBottom = new MonitoredVariable[]{
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground)
};
mAnimationLoop = new Handler();
mAnimation = new Runnable() {
#Override
public void run() {
Debug.Log(TAG, "RUNNING ANIMATION");
final Random RNG = new Random();
for (MonitoredVariable<Integer>[] tBackground: new MonitoredVariable[][] {mTop, mBottom}) {
for (MonitoredVariable<Integer> tColor : tBackground) {
int tRandomColor = RNG.nextInt(255);
//tColor.set(tRandomColor);
Shift.changeOverTime(tColor, tRandomColor, 2000, 100);
}
}
if(mAnimate.get()) {
mAnimationLoop.postDelayed(mAnimation, 10000);
}
}
};
mAnimate = new MonitoredVariable<>(false, new MonitoredVariable.ChangeListener() {
#Override
public void onChange() {
if (mAnimate.get()) mAnimationLoop.postDelayed(mAnimation, 0);
else mAnimationLoop.removeCallbacks(mAnimation);
}
});
}
public static void setBackground(final Activity tActivity){
final View tActivityBackground = tActivity.findViewById(R.id.background);
mListener = new ChangeListener() {
#Override
public void onChange() { tActivityBackground.setBackground(mBackground); }
};
notifyChange();
}
private static void updateBackgroud() {
int tTop = Color.argb(255, mTop[0].get(), mTop[1].get(), mTop[2].get());
int tBottom = Color.argb(255, mBottom[0].get(), mBottom[1].get(), mBottom[2].get());
int[] colors = {tTop, tBottom};
mBackground = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors);
mBackground.setCornerRadius(0f);
notifyChange();
}
public static void animateBackground(boolean tAnimate) {
mAnimate.set(tAnimate);
}
public static void notifyChange() {
if (mListener != null) mListener.onChange();
}
public interface ChangeListener {
void onChange();
}
I am developing an android app using drag and drop. And also I am using an a broadcast receiver for screen on. When I am using setOnDragListener It shows an error:
java.lang.RuntimeException: Error receiving broadcast Intent { act=init view flg=0x10 } in com.app.lockscreenlibrary.LockBroadcastReceiver#f22ed7d
Can anybody please help me solve the issue? Here is my code:
ActivityView.java
public class ActivityView extends FrameLayout {
public LinearLayout drop;
TextView text,sucess;
int total , failure = 0;
ImageView viewDrop;
private GestureDetector gestureDetector;
private Context mContext;
Button btnUnlock;
Button btn1;
private int CLICK_ACTION_THRESHHOLD = 200;
private float startX;
private float startY;
public ActivityView(Context context) {
this(context, null);
}
public ActivityView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ActivityView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(final Context context) {
mContext = context;
View view = inflate(context,R.layout.activity_view,null);
gestureDetector = new GestureDetector(context, new SingleTapConfirm());
drop = (LinearLayout)findViewById(R.id.bottomlinear);
sucess = (TextView)findViewById(R.id.Sucess);
drop.setOnDragListener();
drop.setOnDragListener(new View.OnDragListener() {
#Override
public boolean onDrag(View v, DragEvent event) {
//return false;
final int action = event.getAction();
switch(action) {
case DragEvent.ACTION_DRAG_STARTED:
break;
case DragEvent.ACTION_DRAG_EXITED:
break;
case DragEvent.ACTION_DRAG_ENTERED:
break;
case DragEvent.ACTION_DROP:{
failure = failure+1;
return(true);
}
case DragEvent.ACTION_DRAG_ENDED:{
total = total +1;
int suc = total - failure;
sucess.setText("Sucessful Drops :"+suc);
text.setText("Total Drops: "+total);
return(true);
}
default:
break;
}
return true;
}
});
btnUnlock = (Button) view.findViewById(R.id.unlock);
btnUnlock.setOnClickListener(new OnClickListener() {
#Override public void onClick(View v) {
LockHelper.getLockLayer().unlock();
}
});
btn01 = (Button) view.findViewById(R.id.btn0);
btn1.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.d("LockView", "onTouch");
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();
break;
case MotionEvent.ACTION_UP:
float endX = event.getX();
float endY = event.getY();
if (isAClick(startX, endX, startY, endY)) {
Log.d("LockView", "clicked");
} else {
}
break;
}
v.getParent().requestDisallowInterceptTouchEvent(true); //specific to my project
return false;
}
});
addView(view);
}
}
}
private class SingleTapConfirm extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onSingleTapUp(MotionEvent event) {
Log.d("LockView", "clicked1");
return true;
}
}
private boolean isAClick(float startX, float endX, float startY, float endY) {
float differenceX = Math.abs(startX - endX);
float differenceY = Math.abs(startY - endY);
if (differenceX > CLICK_ACTION_THRESHHOLD/* =5 */ || differenceY > CLICK_ACTION_THRESHHOLD) {
return false;
}
return true;
}
}
LockBroadcastReceiver.java
final public class LockBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = LockBroadcastReceiver.class.getSimpleName();
private volatile boolean bInterruptSupervisor = false;
private ScheduledThreadPoolExecutor mExecutor;
private FutureRunnable mSupervisorRunnable;
private static final int SCHEDULE_TASK_NUMBER = 3;
private PhoneStateChange mPhoneStateChangeCallback;
public void assignPhoneStateChangeCallback(PhoneStateChange phoneStateChangeCallback) {
mPhoneStateChangeCallback = phoneStateChangeCallback;
}
#Override public void onReceive(Context context, Intent intent) {
String mAction = intent.getAction();
//DU.sd("broadcast -----The Intent Action is: ", "" + mAction);
switch (mAction) {
case LockHelper.INIT_VIEW_FILTER:
LockHelper.INSTANCE.initLockViewInBackground(context);
break;
case Intent.ACTION_SCREEN_ON:
refreshBatteryInfo();
bringLockViewBackTopIfNot();
break;
case CoreIntent.ACTION_SCREEN_LOCKER_UNLOCK:
shutdownScheduleExecutor();
break;
case LockHelper.START_SUPERVISE:
bInterruptSupervisor = false;
supervise(context.getApplicationContext());
break;
case LockHelper.STOP_SUPERVISE:
bInterruptSupervisor = true;
break;
case LockHelper.SHOW_SCREEN_LOCKER:
//DU.sd("broadcast", "locker received");
case Intent.ACTION_SCREEN_OFF:
LockHelper.INSTANCE.initialize(context);
LockHelper.INSTANCE.getLockLayer().lock();
bInterruptSupervisor = true;
break;
case Intent.ACTION_POWER_CONNECTED:
//LockHelper.INSTANCE.getLockView().batteryChargingAnim();
break;
case Intent.ACTION_POWER_DISCONNECTED:
//LockHelper.INSTANCE.getLockView().batteryChargingAnim();
break;
case Intent.ACTION_SHUTDOWN:
break;
case "android.intent.action.PHONE_STATE":
TelephonyManager tm =
(TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE);
switch (tm.getCallState()) {
case TelephonyManager.CALL_STATE_RINGING:
mPhoneStateChangeCallback.ringing();
Log.i(TAG, "RINGING :" + intent.getStringExtra("incoming_number"));
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
mPhoneStateChangeCallback.offHook();
//DU.sd(TAG, "off hook");
break;
case TelephonyManager.CALL_STATE_IDLE:
mPhoneStateChangeCallback.idle();
Log.i(TAG, "incoming IDLE");
break;
}
break;
default:
break;
}
}
abstract class FutureRunnable implements Runnable {
private Future<?> future;
public Future<?> getFuture() {
return future;
}
public void setFuture(Future<?> future) {
this.future = future;
}
}
public void supervise(final Context context) {
//DU.sd("service", "supervise");
initScheduleExecutor();
if (mSupervisorRunnable == null) {
mSupervisorRunnable = new FutureRunnable() {
public void run() {
if (bInterruptSupervisor) getFuture().cancel(true);
boolean cameraRunning = false;
Camera _camera = null;
try {
_camera = Camera.open();
cameraRunning = _camera == null;
} catch (Exception e) {
// fail to open camera, secure to ignore exception
//DU.sd("camera exception on supervise");
cameraRunning = true;
} finally {
if (_camera != null) {
_camera.release();
getFuture().cancel(true);
context.sendBroadcast(new Intent(LockHelper.SHOW_SCREEN_LOCKER));
}
}
if (!cameraRunning) context.sendBroadcast(new Intent(LockHelper.SHOW_SCREEN_LOCKER));
}
};
}
Future<?> future =
mExecutor.scheduleAtFixedRate(mSupervisorRunnable, 2000, 500, TimeUnit.MILLISECONDS);
mSupervisorRunnable.setFuture(future);
}
private void bringLockViewBackTopIfNot() {
initScheduleExecutor();
mExecutor.scheduleAtFixedRate(new Runnable() {
#Override public void run() {
LockHelper.INSTANCE.getLockLayer().requestFullScreen();
}
}, 1000, 1000, TimeUnit.MILLISECONDS);
}
private void refreshBatteryInfo() {
initScheduleExecutor();
mExecutor.scheduleAtFixedRate(new Runnable() {
#Override public void run() {
//LockHelper.INSTANCE.getLockView().refreshBattery();
}
}, 2, 2, TimeUnit.MINUTES);
}
private void initScheduleExecutor() {
if (mExecutor == null) {
synchronized (this) {
if (mExecutor == null) mExecutor = new ScheduledThreadPoolExecutor(SCHEDULE_TASK_NUMBER);
}
}
}
public synchronized void shutdownScheduleExecutor() {
if (mExecutor == null) return;
mExecutor.shutdown();
mExecutor = null;
}
}
LockHelper.java
public enum LockHelper implements SwipeEvent {
INSTANCE;
private static Context mContext;
private final int UNLOCK = 830;
private final int UNLOCK_WITH_PASSWORD = 831;
private final int SWITCH_TO_GUEST = 345;
public static final String INIT_VIEW_FILTER = "init view";
public static final String START_SUPERVISE = "start supervise";
public static final String STOP_SUPERVISE = "stop supervise";
public static final String SHOW_SCREEN_LOCKER = "show screen locker";
private static LockView mLockView;
private static LockLayer mLockLayer;
public void initialize(Context context) {
initContextViewAndLayer(context);
loadLockView(context);
}
/**
* #throws NullPointerException if not init
*/
public static LockView getLockView() {
if (mLockView == null)
throw new NullPointerException("init first");
return mLockView;
}
/**
* #throws NullPointerException if not init
*/
public static LockLayer getLockLayer() {
if (mLockLayer == null)
throw new NullPointerException("init first");
return mLockLayer;
}
/**
* #throws NullPointerException if context == null
*/
public void initLockViewInBackground(final Context context) {
if (context == null)
throw new NullPointerException("context == null, assign first");
if (mLockView == null || mLockLayer == null)
initContextViewAndLayer(context);
}
public void initContextViewAndLayer(Context context) {
if (mContext == null)
synchronized (this) {
if (mContext == null)
mContext = context;
}
//init layout view
if (mLockView == null)
synchronized (this) {
if (mLockView == null)
mLockView = new LockView(context);
}
//init lock layer
if (mLockLayer == null)
synchronized (this) {
if (mLockLayer == null)
mLockLayer = LockLayer.getInstance(context, mLockView);
}
}
private volatile boolean mIsInitialized = false;
public void loadLockView(Context context) {
mLockView.showLockHome();
if( !mIsInitialized){
//mLockView.assignSwipeEvent(this);
//
//mLockView.assignDirectionOperator(new SwipeWithAnimListener.DirectionOperator() {
// #Override
// public void up() {
// }
//
// #Override
// public void down() {
//
// }
//
// #Override
// public void left() {
// if(!mLockView.leftSlidable()) return;
//
// mHandler.sendEmptyMessage(UNLOCK);
// }
//
// #Override
// public void right() {
// if(!mLockView.rightSlidable()) return;
//
// mHandler.sendEmptyMessage(UNLOCK);
// }
//});
// mLockView.assignPinCodeRuler(new PinCodeView.UnlockInterface() {
// #Override
// public void onUnlock(String password) {
//
// Message msg = new Message();
// msg.what = UNLOCK_WITH_PASSWORD;
// msg.obj = password;
// mHandler.sendMessage(msg);
// }
//
// #Override
// public void onBack() {
// mLockView.switchBackToCenterFromBottom();
// }
// });
mIsInitialized = true;
}
mLockLayer.lock();
showLockLayer();
}
private Handler mHandler = new Handler(Looper.getMainLooper()) {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UNLOCK:
//DU.sd("handler", "unlock");
unlock();
break;
case UNLOCK_WITH_PASSWORD:
if (!(msg.obj instanceof String)) break;
String password = (String) msg.obj;
switchUserIfExistOrAlertUser(password);
break;
default:
break;
}
}
};
private void unlock() {
mLockLayer.unlock();
//mLockView.stopShimmer();
mContext.sendBroadcast(new Intent(LockHelper.STOP_SUPERVISE));
mContext.sendBroadcast(new Intent(CoreIntent.ACTION_SCREEN_LOCKER_UNLOCK));
}
private void switchUserIfExistOrAlertUser(String password) {
if (TextUtils.isEmpty(password)) {
wrong();
return;
}
if (!password.equals("1234")) {
wrong();
return;
}
unlockScreenAndResetPinCode();
}
private void unlockScreenAndResetPinCode() {
unlock();
// mLockView.resetPinCodeView();
}
private void wrong() {
}
public static final String INTENT_KEY_WITH_SECURE = "with_secure";
#Override
public <S, T> void onSwipe(S s, T t) {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
LockHelper.INSTANCE.getLockLayer().removeLockView();
}
}, 1000);
//triggerCameraWithSecure(mContext, !(t instanceof Boolean) || (Boolean) t);
}
private void triggerCameraWithSecure(Context context, boolean withSecure) {
//if (!CameraHelper.hasCameraHardware(context)) return;
//
//try {
// CameraHelper.cameraStrategy(context, withSecure);
//} catch (Exception e) {
// // may cannot open
// e.printStackTrace();
// showLockLayer();
//}
//
//context.sendBroadcast(new Intent(LockHelper.START_SUPERVISE));
}
private void showLockLayer() {
mLockView.showLockHome();
mLockLayer.bringBackLockView();
}
public void vibrate(long milliseconds) {
if (mContext == null) return;
Vibrator v = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
// Vibrate for 500 milliseconds
v.vibrate(milliseconds == 0 ? 500 : milliseconds);
}
}
There is no problem with the boradcast receiver per se. You have a clear exception in your code
java.lang.ClassCastException: com.happiness.lockscreenlibrary.LockScreenService cannot be cast to android.view.View$OnDragListener at
You are trying to cast an incompatible class type to another. I could not see that part of code in what you pasted here. So, please try to figure that out. Basically the code you are executing on receiving the broadcast has a bug, nothing with the receiver as such
I want to create animation on surfaceview.
Here is a surfaceview:
public class AnimationSurfaceView extends SurfaceView implements SurfaceHolder.Callback{
private AnimationWorker animationWorker;
private GestureDetectorCompat mGestureDetector;
private OverScroller mScroller;
private Cursor mCursor;
private int pIndexA, pIndexB;
private int dir;
private float posX=0;
public AnimationSurfaceView(Context context, Cursor cursor) {
super(context);
getHolder().addCallback(this);
mCursor = cursor;
mGestureDetector = new GestureDetectorCompat(context, mGestureListener);
mScroller = new OverScroller(context);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
animationWorker = new AnimationWorker(getHolder(), getContext(), null);
animationWorker.setRunning(true);
animationWorker.run();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
animationWorker.setRunning(false);
animationWorker.postTask(null);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("sfsfsfdf", "Работает1!!!!!!!!!!!!!!!!!!!");
boolean retVal = mGestureDetector.onTouchEvent(event);
return retVal || super.onTouchEvent(event);
}
#Override
public void computeScroll() {
super.computeScroll();
if(mCursor != null){
int i1 = Math.max(0,Math.min(mCursor.getCount()-1, (int)Math.floor(posX/720f)));
int i2 = Math.max(0,Math.min(mCursor.getCount()-1, (int)Math.ceil(posX/720f)));
if(i1 != pIndexA){
dir = i1-pIndexA;
pIndexA = i1;
pIndexB = i2;
}
}
}
private void updateWorker(){
animationWorker.postTask(new AnimationTask(posX, dir));
AnimationWorker.syncObj.notifyAll();
}
private final GestureDetector.SimpleOnGestureListener mGestureListener
= new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onDown(MotionEvent e) {
mScroller.forceFinished(true);
animationWorker.cancelTaskQueue();
return true;
}
#Override
public boolean onDoubleTap(MotionEvent e) {
return true;
}
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
posX += -distanceX;
updateWorker();
return true;
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
velocityX = - velocityX;
fling(velocityX);
return true;
}
private void fling(float velocity){
mScroller.forceFinished(true);
mScroller.fling((int) posX, 0, (int) -velocity, 0, 0, 720 * (mCursor != null ? mCursor.getCount() : 1), 0, 0);
updateWorker();
}
};
Here is an worker:
public class AnimationWorker extends Thread {
private static final String LOG_TAG = AnimationWorker.class.getSimpleName();
public static final Object syncObj = new Object();
private boolean runFlag = false;
private SurfaceHolder surfaceHolder;
private Context context;
private BlockingQueue<AnimationTask> queue;
private Cursor mCursor;
private AnimationImageCacheHelper animationImageCacheHelper;
private final String ASSET_SUFFIX = "assets://";
private final String FILE_SUFFIX = "file://";
Rect clipRect;
Rect bitmapRect;
Paint paint;
Pair<Bitmap, Bitmap> bitmaps;
int mLeftIndex;
int mRightIndex;
private final Float TRACK_LENTH = 720f;
private final Float MAX_ALPHA = 255f;
public AnimationWorker(
SurfaceHolder surfaceHolder,
Context context,
Cursor cursor){
super();
this.surfaceHolder = surfaceHolder;
this.animationImageCacheHelper = new AnimationImageCacheHelper();
bitmapRect = new Rect();
paint = new Paint();
clipRect = new Rect();
queue = new LinkedBlockingDeque<AnimationTask>();
}
public void setRunning(boolean run){
runFlag = run;
}
public void postTask(AnimationTask task){
try {
queue.put(task);
}catch (Exception e){
//do nothing
}
}
public void cancelTaskQueue(){
queue.clear();
}
#Override
public void run() {
while(runFlag){
Log.e(LOG_TAG, "running");
try {
AnimationTask task = queue.remove();
if(task != null) {
processTask(task);
}
}catch(Exception e){
try {
synchronized (syncObj) {
syncObj.wait();
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
Log.e(LOG_TAG, "exception");
e.printStackTrace();
}
}
}
private void processTask(AnimationTask task){
int leftIndex = Math.max(0,Math.min(mCursor.getCount()-1, (int)Math.floor(task.currentPosition/TRACK_LENTH.intValue())));
int rightIndex = Math.max(0,Math.min(mCursor.getCount()-1, (int)Math.ceil(task.currentPosition/TRACK_LENTH.intValue())));
if(mLeftIndex != leftIndex || mRightIndex != rightIndex){
bitmaps = getBitmaps(leftIndex, rightIndex, task.direction);
}
float alpha = (MAX_ALPHA / TRACK_LENTH * task.currentPosition) % MAX_ALPHA;
draw(bitmaps.first, bitmaps.second, alpha);
}
private Pair<Bitmap, Bitmap> getBitmaps(int leftIndex, int rightIndex, int direction){
final Bitmap foregroundBitmap;
final Bitmap backgroundBitmap;
final Pair<Bitmap, Bitmap> result;
if(direction == 1) {
//right on top
if(mCursor.moveToPosition(leftIndex)){
String backgroundImageUrl = mCursor.getString(mCursor.getColumnIndex(PhotoContract.PhotoEntry.COLUMN_PHOTO_URL));
backgroundBitmap = loadImage(backgroundImageUrl);
}else{
backgroundBitmap = null;
}
if (mCursor.moveToPosition(rightIndex)){
String foregroundImageUrl = mCursor.getString(mCursor.getColumnIndex(PhotoContract.PhotoEntry.COLUMN_PHOTO_URL));
foregroundBitmap = loadImage(foregroundImageUrl);
}else{
foregroundBitmap = null;
}
} else {
//left on top
if(mCursor.moveToPosition(rightIndex)){
String backgroundImageUrl = mCursor.getString(mCursor.getColumnIndex(PhotoContract.PhotoEntry.COLUMN_PHOTO_URL));
backgroundBitmap = loadImage(backgroundImageUrl);
}else{
backgroundBitmap = null;
}
if (mCursor.moveToPosition(leftIndex)){
String foregroundImageUrl = mCursor.getString(mCursor.getColumnIndex(PhotoContract.PhotoEntry.COLUMN_PHOTO_URL));
foregroundBitmap = loadImage(foregroundImageUrl);
}else{
foregroundBitmap = null;
}
}
result = new Pair<Bitmap, Bitmap>(foregroundBitmap, backgroundBitmap);
return result;
}
private Bitmap loadImage(String uri){
if(animationImageCacheHelper.isImageContains(uri)){
return animationImageCacheHelper.getBitmap(uri);
}
if (uri.startsWith(ASSET_SUFFIX)) {
Bitmap bitmap = ImageLoader.getInstance().loadImageSync(uri);
animationImageCacheHelper.put(uri, bitmap);
return bitmap;
} else {
Bitmap bitmap = ImageLoader.getInstance().loadImageSync("file://" + uri);
animationImageCacheHelper.put(uri, bitmap);
return bitmap;
}
}
private void draw(Bitmap foreground, Bitmap background, float alpha){
Canvas canvas;
canvas = null;
try {
canvas = surfaceHolder.lockCanvas(null);
canvas.getClipBounds(clipRect);
synchronized (surfaceHolder) {
//draw background
paint.setAlpha(255);
bitmapRect.set(0, 0, background.getWidth(), background.getHeight());
canvas.drawBitmap(background, bitmapRect, clipRect, paint);
//draw foreground
paint.setAlpha((int)alpha);
bitmapRect.set(0, 0, foreground.getWidth(), foreground.getHeight());
canvas.drawBitmap(foreground, bitmapRect, clipRect, paint);
}
}finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
I'm listening onTouch events and add task(current position and direction) for worker. Worker must getting task from queue and draw current state.
In my version nothing happens. Surfaceview freeezes and I need pull battery from my device to unlock it.
*Note: I'm tried use queue.take() - but I get same result
Is it possibble to Limit the touch event of the SlidingPaneLayout to the very left edge of the screen link happens in the DrawerLayout?
Yes, but you want to create your own implementation of SlidingPaneLayout and override onTouchEvent(MotionEvent ev) method, like this
public class SlidingPaneLayoutExtended extends SlidingPaneLayout {
public static final int DEFAULT_DRAGGING_START_X = -1;
public static final int SLIDE_FROM_LEFT_EDGE = 0;
private int startDraggingX = DEFAULT_DRAGGING_START_X;
public SlidingPaneLayoutExtended(Context context, AttributeSet attrs) {
super(context, attrs);
}
public int getStartDraggingX() {
return startDraggingX;
}
public void setStartDraggingX(int startX) {
this.startDraggingX = startX;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
if (startDraggingX > DEFAULT_DRAGGING_START_X) {
if ((startDraggingX == SLIDE_FROM_LEFT_EDGE && ev.getAction() == )
|| ev.getX() <= DEFAULT_DRAGGING_START_X) {
return super.onTouchEvent(ev);
} else {
return false;
}
}
return super.onTouchEvent(ev);
}
}