I am trying to make a Helicopter-like game (as you can probably tell, I'm using "Rocket Man" instead of a helicopter). I'm new to Android programming and to Stack Overflow, so don't pick apart my code too much (please). Anyway, right now I'm just trying to get the rocketman to move up while touch is held down, and move down while touch is released.
It isn't working out very well.
I'm using a Moto XT886 for testing, (in case that's relevent). When I run the application, it starts up and loads the MainActivity perfectly well. When I touch the screen the first time (boolean start == true), the text views are hidden, as they are supposed to. However, on the second, third, fourth and all the rest of the times I touch the screen (Start == false), nothing happens. There are no errors in Log Cat, the code doesn't seem to recognize the touch.
I'm pretty sure that it has something to do with those while loops, but I'm using this application mainly to learn Android Java and I don't know enough (yet) to recognize that I'm doing something wrong. Are you able to put a while loop with the conditions as the MotionEvent of an onTouchListner? Or is it something else?
Either way, I appreciate the help, this is an awesome website (this is the first question I couldn't find already asked on Stack Overflow, and for all I know, mine could've already been answered)!
Here's the code to my MainActivity, if you need the .xml code as well, (though I'm pretty sure that's unnecessary) just say the word.
public class MainActivity extends ActionBarActivity {
boolean Start;
RelativeLayout rLayout;
TextView gameTitle;
TextView clickStart;
TextView highScore;
Handler handler;
ImageView rocketMan;
float Y;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initialize();
rLayout.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (Start == true) {
gameTitle.setVisibility(View.GONE);
clickStart.setVisibility(View.GONE);
highScore.setVisibility(View.GONE);
Start = false;
}
if (Start = false) {
while (event.getAction() == MotionEvent.ACTION_DOWN) {
Y = -7;
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
Thread.sleep(100);
handler.post(new Runnable() {
#Override
public void run() {
HeliMove();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
while (event.getAction() != MotionEvent.ACTION_DOWN) {
Y = 7;
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
Thread.sleep(100);
handler.post(new Runnable() {
#Override
public void run() {
HeliMove();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
return true;
}
});
}
private void initialize() {
rLayout = (RelativeLayout) findViewById(R.id.mainlayout);
Start = true;
gameTitle = (TextView) findViewById(R.id.rocketmanTitle);
clickStart = (TextView) findViewById(R.id.tapToStart);
highScore = (TextView) findViewById(R.id.highScore);
handler = new Handler();
rocketMan = (ImageView) findViewById(R.id.rocketMan);
}
private void HeliMove() {
rocketMan.setY(rocketMan.getY() + Y);
}
}
Thanks a million!
Related
I'm currently having problems with Google vision. There is nothing wrong with the library actually, its works great. All what I'm trying to accomplish now is set a rectangular area where the CameraSource will focus only on. The aim is try to capture text within that particular rectangular box only. I've tried many examples on StackOverflow but they all didn't seem to work. My current working code with the Google Vision ( 11.8.0 ) is
cameraView = findViewById(R.id.surfaceview);
output = findViewById(R.id.output);
TextRecognizer textRecognizer = new TextRecognizer.Builder(ScanVoucher.this).build();
if(!textRecognizer.isOperational()) {
show_alert("Text Recognition not supported on this device");
} else {
cameraSource = new CameraSource.Builder(ScanVoucher.this, textRecognizer)
.setAutoFocusEnabled(true)
.setFacing(CameraSource.CAMERA_FACING_BACK)
.setRequestedFps(2.0f)
.setRequestedPreviewSize(300, 300)
.build();
cameraView.getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
try {
cameraSource.start(cameraView.getHolder());
} catch (IOException e) {
show_alert("Unable to access camera");
} catch (SecurityException e) {
finish();
} catch(Exception e) {
//Kill
finish();
}
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
cameraSource.stop();
}
});
textRecognizer.setProcessor(new Detector.Processor<TextBlock>() {
#Override
public void release() {
}
#Override
public void receiveDetections(Detector.Detections<TextBlock> detections) {
final SparseArray<TextBlock> items = detections.getDetectedItems();
if(items.size() != 0) {
output.post(new Runnable() {
#Override
public void run() {
StringBuilder builder = new StringBuilder();
for(int i = 0; i < items.size(); i++) {
TextBlock item = items.valueAt(i);
builder.append(item.getValue());
}
try {
output.setText(builder.toString());
} catch (Exception e) {
output.setText(e.getMessage());
}
}
});
}
}
});
}
As I said, everything works great. Wondering how I could set the rectangular box like preview area so that the camera only captures text with the box just like the QR or bar code scanner apps. Thanks in advance.
Please dont abandon project.. You can Reset your .setRequestedPreviewSize(80, 24) to fit.
for me, this only captures the first text line. i hope you see this
I am trying to play with progress bars. I have this (below) simple activity which runs a progress bar N times one after the other, when I call Progress(N). It is working great but the problem I am facing is, if I press back button. I get into the mainActivity but the progress bars (the threads) are still running in background one after the other. As soon as they finish N loops, the intent is called and whatever I would be doing would be interrupted by this LOOP_OVER activity.
I tried solving this by my own. I tried using variable of Thread class (before I was directly doing it). And tried to interrupt() it at onDestroy() or even just before the intent is called but its not helping. How should I go about it?
public class Loop extends Activity {
private ProgressBar progressBar;
private CircleProgress circleProgress;
private int progressStatus = 0;
private Handler handler = new Handler();
private TextView myView;
private int started = 0, doneLoop=0;
private Thread th;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_loop);
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
circleProgress = (CircleProgress) findViewById(R.id.circle_progress);
myView = (TextView) findViewById(R.id.instruction);
progressBar.setScaleY(3f);
// Start long running operation in a background thread
Progress(3);
}
#Override
public void onDestroy() {
// Below, everything I am just
th.interrupt();
Loop.this.finish();
Thread.currentThread().interrupt();
super.onDestroy();
}
public void Progress(final int numberOfRuns){
// QueView.setText(Que);
if(numberOfRuns == 0){
th.interrupt();
Intent myIntent = new Intent(Loop.this, LOOP_OVER.class);
startActivity(myIntent);
super.onDestroy();
finish();
}
th = new Thread(new Runnable() {
public void run() {
genNextSet();
while (progressStatus < 100) {
progressStatus += 1;
// Update the progress bar and display the
//current value in the text view
handler.post(new Runnable() {
public void run() {
circleProgress.setProgress(progressStatus);
progressBar.setProgress(progressStatus);
textView.setText(progressStatus+"/"+progressBar.getMax());
}
});
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
myView.setText(Que);
}
});
// Sleep for 200 milliseconds.
//Just to display the progress slowly
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
progressStatus = 0;
Progress(numberOfRuns - 1);
}
});
th.start();
}
private void genNextSet() {
// so some cool here!
}
}
You can think of a class variable that is shared among all threads.
Try to add something like this:
private Boolean LOOP = true;
then
while (progressStatus < 100 && LOOP) {
and
#Override
public void onBackPressed() {
LOOP = false
}
also
if(LOOP == true){
// call intent
}
finish();
Your activity does not get destroyed, if you press the "Back"-key, thus onDestroy() will not be called.I'd override onBackPressed(), if I where you.Alternatively, you could try to put it into the onPause()-method.
You haven't override the back button pressed..try this
#Override
public void onBackPressed() {
th.interrupt();
Loop.this.finish();
Thread.currentThread().interrupt();
super.onBackPressed();
// add finish() if you want to kill current activity
}
I am trying to do this simple task. I have two buttons called START and STOP, I want to execute some task in loop by clicking on START and want to exit from this loop by clicking STOP.
Code-
public class DrawPath extends Activity implements View.OnClickListener {
ArrayList<LatLng> positions = new ArrayList<LatLng>() ;
static int c=1;
Location location;
GoogleMap mMap;
Button btStart,btStop;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.drawpath);
initializeVar();
btStart.setOnClickListener(this);
btStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
c = 0;
System.out.println("tested2");
}
});
}
private void initializeVar()
{
btStart=(Button)findViewById(R.id.btStart);
btStop=(Button)findViewById(R.id.btStop);
}
#Override
public void onClick(View v) {
getupdate(1);
}
private void getupdate(int d) {
c = d;
CurrentPosition currentPosition = new CurrentPosition(this);
if (c == 0) {
System.out.println("Done");
} else {
location = currentPosition.getCurrentLocation();
LatLng pos = new LatLng(location.getLatitude(), location.getLongitude());
positions.add(pos);
System.out.println("running");
try {
Thread.sleep(5000);
getupdate(c);
} catch (Exception e) {
}
}
}
}
Somebody please share any idea how to achieve it.
You can use Handler with Runnable to stop your thread after STOP button click.
I am giving you hint use following code according to your requirement
Handler handler = new Handler();
Runnable runable = new Runnable({
#Override
public void run(){
// count
handler.postDelayed(this, 1000);
}
});
Now you can call following line from your btnStop.onClick().
handler.removeCallbacks(runable);
Check this for more details on Handler and Runnable
What I suggest it create a inner class which extends Thread and according to user's action start and stop the thread. here is an example
class DrawPath extends Activity implements View.OnClickListener {
MyThread thread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.drawpath);
initializeVar(); //not in my code so you add it
btStart.setOnClickListener(this);
btStop.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btStart:
if (thread == null) {
thread = new MyThread();
thread.start();
}
break;
case R.id.btStop:
if (thread != null) {
thread.interrupt();
}
break;
}
}
class MyThread extends Thread {
#Override
public void run() {
while (true) {
try {
Thread.sleep(3000);
//your stuff goes here or before sleep
} catch (InterruptedException e) {
e.printStackTrace();
thread = null;
break;
}
}
}
}
//whey interrupt here bcz infinite loop will be running until and unless you stop it.
#Override
protected void onDestroy() {
super.onDestroy();
if (thread != null)
thread.interrupt();
}
}
I saw your code which needs little more improvements that's why I wrote this big file :)
Suggestions :
Checkout the implementation of onClickListener.
Stopping thread at onDestroy() because thread will be running even after you close your application, so you need to stop when you
come out (destroyed) of your main activity.
I'm currently creating a custom double tap using the onClickListener with the following code:
newImage.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
counterTap++;
Timer t = new Timer("Double tap counter");
t.schedule(new TimerTask() {
#Override
public void run() {
counterTap = 0;
}
}, 0, 300);
if(counterTap >= 2) {
newImage.setVisibility(FrameLayout.GONE);
counterTap = 0;
}
}
});
The problem I'm facing is as follows:
Whenever I tap the ImageView the event does fire. However, the second time I tap the ImageView, the above code only executes when clicking on the exact same position on the ImageView as before.
Rather use a onTouchListener. In the touch listener in the onTouch method you can return false the first time you tapped which means the event was not handled, the second time you return true and the touch listener will handle the event as finished. See my example below, you can use a similar method
new OnTouchListener() {
boolean doubleTap = false;
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
if (!doubleTap) {
doubleTap = true;
return false;
} else {
return true;
}
}
}
};
this might solve your issue.
EDIT : This is a better opotion
private class GestureListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onDown(MotionEvent e) {
return true;
}
// double tap event
#Override
public boolean onDoubleTap(MotionEvent e) {
return true;
}
}
This question might also help you get to the best answer
This has been really confusing me of late. I have a thread which I start, and it keeps running until I kill it - by setting it's while variable to false.
This all works ok, but I lose contact with the thread on orientation change so I can't stop it. I've written this to try and clarify the problem:
public class FTTest extends Activity {
boolean isPlaying = false;
Player player = new Player();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fttest);
}
public void play(View v) {
if (!isPlaying) {
Log.d("Play Button", "Start Pressed");
player.start();
isPlaying = true;
} else {
Log.d("Play Button", "Stop Pressed");
player.going=false;
isPlaying = false;
}
}
}
The player is just this:
public class Player extends Thread{
int i;
public boolean going=true;
public void run(){
while(going){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
Log.d("Thread", "Running "+i+" times");
}
}
}
I've been reading about using fragments to solve this - but I just can't get my head around how to use them in this context. Is there something simple I'm missing?
Thanks for your help,
Mike
The idea is that you allow a fragment to be retained (fragment is not destroyed.. it will be persisted across your orientation changes). Your activity will get recreated and will be reattached to your Fragment which is still running your thread..
public class FTTest extends Activity {
private FTFragment fragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
fragment = new FTFragment();
getFragmentManager().beginTransaction().add(android.R.id.content, fragment).commit();
}
else {
fragment = (FTFragment)getFragmentManager().findFragmentById(android.R.id.content);
}
}
}
Retained fragment class
public class FTFragment extends Fragment
{
boolean isPlaying = false;
Player player = new Player();
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
public void play(View v) {
if (!isPlaying) {
Log.d("Play Button", "Start Pressed");
player.start();
isPlaying = true;
} else {
Log.d("Play Button", "Stop Pressed");
player.going=false;
isPlaying = false;
}
}
}
In your activity where you called play(View) you now should call fragment.play(View);
I think what is happening is that on your orientation change, the activity is getting recreated (as it usually does in android). When this happens, the Player object is being re-initialised as well.
So, you are actually going to have a reference to a new Player object and the old one will keep on running happily outside your control.
There are many ways to handle this. This blog post will be of help:
http://blog.andresteingress.com/2011/09/27/fighting-orientation-changes-in-android/