I think my problem is very basic but i am new to android so just need this solution.
I have 20 buttons and all of them are animating(translation and scaling) on the screen. I want to create a new thread and do animations there. Those buttons have images on them,code is working fine in UI thread but sometimes i am getting ANR message and exception that application may be doing too much work on its main thread.
Please help
Thank you
This is my onCreate in which i want to do animations inside thread:-
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
playerName=getSharedPreferences(WelcomeActivity.Player_Name,0);
gameMode= getSharedPreferences("game_mode", 0);
setContentView(R.layout.activity_dragonland);
shendron=(ImageView)findViewById(R.id.shendron);
glaedr=(ImageView)findViewById(R.id.glaedr);
saphira=(ImageView)findViewById(R.id.saphira);
brownlay=(ImageView)findViewById(R.id.brownlay);
chrysophylax=(ImageView)findViewById(R.id.chrysophylax);
tempest=(ImageView)findViewById(R.id.tempest);
thrisorn=(ImageView)findViewById(R.id.thrisorn);
ruth=(ImageView)findViewById(R.id.ruth);
grifoka=(ImageView)findViewById(R.id.grifoka);
horrid=(ImageView)findViewById(R.id.horrid);
brownmean=(ImageView)findViewById(R.id.brownmean);
firnen=(ImageView)findViewById(R.id.firnen);
rhaegal=(ImageView)findViewById(R.id.rhaegal);
mnementh=(ImageView)findViewById(R.id.mnementh);
gorep=(ImageView)findViewById(R.id.gorep);
rubela=(ImageView)findViewById(R.id.rubela);
hotrika=(ImageView)findViewById(R.id.hotrika);
drako=(ImageView)findViewById(R.id.drako);
cadui=(ImageView)findViewById(R.id.cadui);
balerion=(ImageView)findViewById(R.id.balerion);
dragon_zoom = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.dragon_zoom);
dragon_zoom.setStartOffset(1500);
down_right = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.down_right);
up_right = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.up_right);
seq_down= AnimationUtils.loadAnimation(getApplicationContext(),R.anim.sequential_down);
seq_up= AnimationUtils.loadAnimation(getApplicationContext(),R.anim.sequential_up);
seq_right= AnimationUtils.loadAnimation(getApplicationContext(),R.anim.sequntial_right);
seq_left= AnimationUtils.loadAnimation(getApplicationContext(),R.anim.sequential_left);
shendron.startAnimation(dragon_zoom);
glaedr.startAnimation(seq_down);
saphira.startAnimation(down_right);
brownlay.startAnimation(seq_up);
chrysophylax.startAnimation(seq_right);
tempest.startAnimation(up_right);
thrisorn.startAnimation(dragon_zoom);
ruth.startAnimation(down_right);
grifoka.startAnimation(down_right);
horrid.startAnimation(dragon_zoom);
brownmean.startAnimation(dragon_zoom);
firnen.startAnimation(dragon_zoom);
rhaegal.startAnimation(seq_right);
mnementh.startAnimation(up_right);
gorep.startAnimation(seq_left);
rubela.startAnimation(seq_left);
hotrika.startAnimation(seq_left);
drako.startAnimation(seq_left);
cadui.startAnimation(dragon_zoom);
balerion.startAnimation(up_right);
}
you can use something like this:
Thread thread = new Thread()
{
#Override
public void run() {
try {
Animation ranim = (Animation) AnimationUtils.loadAnimation(getBaseContext(),
R.anim.rotation);
buttonRotate.setAnimation(ranim);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
Related
I am trying to accomplish fireworks functionality based on the github code from Lenoids. I want to create two fireworks (one white and another red) and have them display continuously after every two seconds.
Here's what I did so far:
Created two buttons (one for each color of fireworks). The buttons have the fireworks functionality.
Call the buttons programatically in a thread to display the fireworks.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_congratulations);
new Thread(new Runnable() {
#Override
public void run() {
while(true){
try {
Thread.sleep(100);
button10.callOnClick(); //for red fireworks
button11.callOnClick(); //for white fireworks
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
The problem is that if I increase the value of sleep method, then the fireworks do not show up at all. How can I accomplish the two second continuous fireworks functionality?
Here's the fireworks code:
new ParticleSystem(MyClass.this, 100, R.drawable.star_pink, 800) .setSpeedRange(0.1f, 0.25f) .oneShot(view, 70);
If you want to run the firework every two seconds then use Handler instead of the thread and thread.sleep.
final Handler ha=new Handler();
ha.postDelayed(new Runnable() {
#Override
public void run() {
button10.callOnClick();
button11.callOnClick();
ha.postDelayed(this, 2000);
}
}, 2000);
Hope that helps.
I am trying to process some files and it takes some time, so I would like to use a progressBar while the operation is being performed. In my activity, I have a button which starts the processing, when I press on it, the progressBar does not update and after a while the operation is complete and I see the result of the processing (so the function is properly called and act as expected).
The progressBar is visible, it just does not update. I have displayed getProgress() in the log and the value increases, only the actual progressBar does not update.
The function which should update the progressBar:
private byte[] processFiles() throws ExecutionException, InterruptedException {
//Init things
final ArrayList<String> fileNames = getFileList();
progressBar.setVisibility(View.VISIBLE);
progressBar.setMax(fileNames.size());
progressBar.setIndeterminate(false);
for (int i = 0 ; i<fileNames.size(); i++) {
//Do stuff on files
progressBar.setProgress(i+1);
Log.d("CurrentActivity", String.valueOf(progressBar.getProgress()));
}
return bos.toByteArray();
}
In the onCreate():
progressBar = (ProgressBar) findViewById(R.id.progressBar);
progressBar.setIndeterminate(false);
I have also tried as displayed in the android developer tutorial using a Thread but with no success (though I did not use a while loop but a for loop, but figured it shouldn't matter).
Can anyone help me figure out the problem?
Note I have also tried to use this before each update as suggested in some other answers:
progressBar.setProgress(0);
progressBar.setMax(fileNames.size());
Edit, here is my onClickListener:
fileButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
// Init things
try{
new Thread(new Runnable() {
public void run() {
try {
outStream = new FileOutputStream(path);
outStream.write(processFiles());
outStream.close();
runOnUiThread(new Runnable() {
#Override
public void run() {
//stuff that updates ui
}
});
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}catch(Exception e){
e.printStackTrace();
}
}
});
Now the progressBar works but using processedFile fails, it is an image that I display with Glide, it worked well before but now it doesn't display anything.
Edit 2: using runOnUiThread for all UI update worked like a charm and fixed my new issue.
You need to use two threads:
Main Thread (aka UI Thread) (aka WhereYouWorkAlways Thread)
Find and store the ProgressBar, create a Handler and then create the new Thread (see below)
Work Thread (aka just a new thread)
Inside the Thread Runnable, after each step of the work (= after each file operation is done) post a Runnable at the handler which updates the progress bar
handler.post(new Runnable() {
public void run() {
progressBar.setProgress(i);
}
})
Why two Threads are needed
The main thread is actually the UI Thread which means that every operations is placed in the "Update" step of the following cycle:
-> Update -> (Re)Draw -> Wait ->
Which means that if the Update lasts 10s then the screen will update after 10s. (Most UIs are single thread based)
Because on each iteration of cycle you have progressBar.setProgress(0);
I have a problem with my Thread, the Thread doesn't start, I don't have any idea why it doesn't run.
This is my code,
public class MainActivity extends AppCompatActivity {
TextView tv;
int seg=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView)findViewById(R.id.reloj);
}
boolean on=false;
public void inicia(View view){
if(!on){
tiempo.start();
on=true;
}
}
Thread tiempo=new Thread(){
public void run(){
try{
while(true){
Thread.sleep(1000);
seg++;
tv.setText(seg+"");
}
}catch (InterruptedException e){
}
}
};
}
prints this error
Only the original thread that created a view hierarchy can touch its views.
Well first off I'm assuming you set an onClick in you xml to set inicia to be the click handler for the button. Otherwise, that's part of your problem.
You thread is in an infinite loop. The while loop would only exit if an interrupt occurred for some reason, and there's nothing that would do that. If you want to post accio every second, the post needs to be inside the while loop.
while(true){
Thread.sleep(1000);
}
The thread is sleeping all the time.
Ok lets try,
Thread will be created from the main looprer thread. So, Your textview will be updated only by mainlooper thread,. When you create the thread, it will start become another thread. it is not related with MainLooper thread, You have to use Handler class to update the textView or use Asynctask or runOnUiThread method to update your text view.
runOnUiThread(new Runnable() {
#Override
public void run() {
textview.settext("");
}
});
Why i can't force Android ANR with this code?
No log messages or pop up. The application is just launched lazily.
[UPDATE]
I can't get it even sleeping a View.setOnClickListener or BroadcastReceiver.onReceive!
Is there a trick?
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
Log.e("Test", "", e);
}
}
}
I'm using Samsung GT-6200L with stock Android 3.2
Try it in onTouchEvent. In onCreate your activity is not fully running
#Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG,"onTouchEvent");
while(true) {}
}
The ANR-WatchDog project has a test app that produces ANRs in a reliable manner (as reliable as ANRs can be): the app hangs because of a deadlock.
The gist of it:
Prepare a lock object as a private field in your activity:
final Object mutex = new Object();
Have a thread that performs some work in a critical section, and an android.os.Handler that posts work depending on the same lock.
new Thread(new Runnable() {
#Override
public void run() {
synchronized (mutex) {
while (true) {
try {
Thread.sleep(60000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
synchronized (mutex) {
// Shouldn't happen
throw new IllegalStateException();
}
}
}, 1000);
Putting the above code snippet inside a button click handler, for example, should do the trick.
I've been facing the same issue yesterday, and I've found out that using a plain debug build ANR dialogs simply won't show up. (Although the UI thread was completely hanged.)
But after exporting and properly signing the application the dialogs were popped up properly (in every cases mentioned above). However I am still not sure what really prevents to pop up ANR messages, maybe someone else can clarify this later...
Try using:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int a=0;
while(true) {
a++;
}
}
Your code probably didn't work because it got setup too early, and the Activity probably wasn't fully initialized and created yet. With the above code, launch the activity and touch/swipe on the screen and wait for the ANR dialog to popup.
Make a button in your activity.
public void onBtn1(View v) {
int a = 0;
while(true) {
a++;
}
}
Make the button execute the above code.
Spam click the button with your finger =)
I used this code for force ANR
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void force(View view){
while(true) {}
}
I just created a simple button in the xml file and set android:onClick=force
i'm making a 15 puzzle (http://en.wikipedia.org/wiki/Fifteen_puzzle) game, and i have an activity for user to select the background image, and then i pass that image to a new activity in order to scale and crop it.
Now i want to show the solution to the user first for 3 secs then it would shuffle, i'm using code like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//...skip the code that gets the image and scales it
start();
}
then in my start() funcion:
public void start() {
//the createPuzzle function would create all the Views(tiles)
//and add them to the root LinearLayout using addView() function
createPuzzle(game.getBoardConfig(), dimension);
//i was trying to sleep here
shuffle();
}
i used:
try {
Thread.sleep(3000);
} catch (InterruptedException e) {}
or:
SystemClock.sleep(3000);
but neither of them worked properly, they all paused the the thread right after i selected the image and when it was paused i can't see the new activity and the tiles i created. When the thread resumes, it was already showing the shuffled puzzle.
I've been looking at the documentation for quite a while but still can't figure out what's wrong with my code, thanks for helping!
Don't make the UI thread sleep because that will lock up the entire UI thread which is a no-no. Instead, use a Handler to post a runnable with a delay...like
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
shuffle();
}
}, 3000);