How to set up ProgressBar for inputStream? - java

I'm trying to setup ProgressDialog to show to the user the progress of an InputStream of bytes. I'm able to show this in the console of the Android Studio by way of this below :
Log.d(TAG, "Progress, transferred " + Integer.toString(100 * bytesTransferred/osSize) + "%");
However, I'm not sure how to attach the bytesTransferred/osSize correctly to a ProgressDialog, I can use a thread to time how long the progress bar will take to fill up the progressBar with the code below:
update = new ProgressDialog(this);
update.setTitle("Transferring update");
update.setMessage("Please wait updating...");
update.setCanceledOnTouchOutside(false);
update.setProgress(0);
final int totalProgressTime = 100;
final Thread t = new Thread() {
#Override
public void run() {
int jumpTime = 0;
while(jumpTime < totalProgressTime) {
try {
sleep(1800);
jumpTime += 1;
update.setProgress(jumpTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t.start();
update.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
update.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
update.show();
}
But would be much better to show to the user the actual transfer of the bytes. This below is what I have to work with:
final int osSize;
final InputStream inputStream;
osSize = inputStream();
public void onProgress(int bytesTransferred) {
Log.d(TAG, "Progress, transferred " + Integer.toString(100 * bytesTransferred/osSize) + "%");
}
Any help would be appreciated, thanks in advance.

Extend this:
#Override
public void run() {
int jumpTime = 0;
while(jumpTime < totalProgressTime) {
try {
sleep(1800);
jumpTime += 1;
update.setProgress(jumpTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
With this:
#Override
public void run() {
int jumpTime = 0;
while(jumpTime < totalProgressTime) {
try {
sleep(1800);
jumpTime += 1;
final int fJumpTime = jumpTime;
runOnUiThread(new Runnable() {
#Override
public void run() {
update.setProgress(fJumpTime);
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

Related

OutOfMemory Exception in Android-Java. Allocation failed due to fragmentation

So I developed an Android application which acts as a server for my Android game(two separated apps), both applications were written in Java.
Previously I got messages on the Log like: "Skipped 2000 frames. The main thread could be overworking".
This is the code of my app, it's made of only the MainActivity:
I tried to introduce concurrent Threads in order to make the main thread lighter. Now the skipped n frames message isn't showed anymore but messages such like the followings are shown anyways.
"Alloc concurrent copying GC freed", "Starting a blocking GC alloc", "Waiting for a blocking GC alloc", "WaitForGcToComplete blocked alloc on HeapTrim" and all of this ends with
Throwing OutOfMemoryError "Failed to allocate a 32 byte allocation with 15604408 free bytes and 14MB until OOM, target footprint 268435456, growth limit 268435456; failed due to fragmentation (largest possible contiguous allocation 0 bytes)" (VmSize 5539048 kB).
I tried to deallocate some objects (lines of code which contains "x = null") but it didn't solve. Furthermore I checked with a log if there is some sort of endless loop but it doesn't seem to be the case.
public class MainActivity extends AppCompatActivity {
private static ActivityMainBinding binding;
private WSocServer server;
private int port = 8080;
private boolean isOnline = false;
private static ArrayList<String> logs = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
binding.openConnection.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(!isOnline) {
isOnline = true;
server = new WSocServer(port);
server.start();
Toast toast = Toast.makeText(view.getContext(),"Server is on", Toast.LENGTH_LONG);
toast.show();
Log.i("WebSocket Server", "Started on port " + server.getPort());
}
else{
Snackbar snack = Snackbar.make(view ,"We are already online!", Snackbar.LENGTH_INDEFINITE);
snack.setAction("Got it", new View.OnClickListener() {
#Override
public void onClick(View view) {
snack.dismiss();
}
});
snack.show();
}
}
});
binding.closeConnection.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(isOnline) {
isOnline = false;
logs.clear();
Toast toast = Toast.makeText(view.getContext(),"Server is off", Toast.LENGTH_LONG);
toast.show();
try {
server.stop();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else{
Snackbar snack = Snackbar.make(view ,"We are already offline!", Snackbar.LENGTH_INDEFINITE);
snack.setAction("Got it", new View.OnClickListener() {
#Override
public void onClick(View view) {
snack.dismiss();
}
});
snack.show();
}
}
});
}
private static void addOnView(){
ConstraintLayout cl = binding.logsView;
Handler h = new Handler(Looper.getMainLooper());
for(int i = 0; i < logs.size(); i++){
TextView tv = new TextView(binding.getRoot().getContext());
tv.setTextSize(16);
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
tv.setPadding(40,180*(i+1),40,0);
tv.setText(logs.get(i));
Runnable r = new Runnable() {
#Override
public void run() {
cl.addView(tv);
}
};
h.post(r);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
try {
server.stop();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static class WSocServer extends WebSocketServer {
private List<String> matchUsers;
private Integer timerSeconds;
private UUID matchId;
//a key represents a match to which an array of extracted numbers is associated
private Hashtable<String,Integer[]> matchExtractedNumbers = new Hashtable<>();
private Hashtable<String, Collection<WebSocket>> matchClients = new Hashtable<>();
private Hashtable<String,Hashtable<String,ArrayList<String>>> users_scorePerMatch = new Hashtable<>();
private Hashtable<String,WebSocket> clientConnection = new Hashtable<>();
private void initTimer(){
timerSeconds = 60;
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
if(timerSeconds > 0) timerSeconds--;
else {
timerSeconds = 60; timer.cancel(); timer.purge();
}
}
};
timer.schedule(task,0L,1000L);
}
private String UsersListToString(List list){
return list.toString().replace("[","").replace("]","");
}
private Integer[] generateExtractedNumbers(){
Integer[] callerBoard = new Integer[90];
List<Integer> boardPool = new ArrayList<>();
boardPool.addAll(Arrays.asList(IntStream.rangeClosed(1,90).boxed().toArray(Integer[]::new)));
for(int i = 0; i < 90; i++){
int rng = ThreadLocalRandom.current().nextInt(0,90-i);
callerBoard[i] = boardPool.remove(rng);
}
return callerBoard;
}
private void initMatch(){
matchId = UUID.randomUUID();
Integer[] matchBoard = generateExtractedNumbers();
matchExtractedNumbers.put(matchId.toString(),matchBoard);
matchClients.put(matchId.toString(),clientConnection.values());
Hashtable<String,ArrayList<String>> matchData = new Hashtable<>();
for(String user: matchUsers) matchData.put(user,new ArrayList<>());
users_scorePerMatch.put(matchId.toString(), matchData);
}
private Integer getExtractedNumber(String match, Integer turn){
if(turn >= 90) return -1;
Integer[] thisMatchExtractedNumbers = matchExtractedNumbers.get(match);
Integer returning = thisMatchExtractedNumbers[turn];
thisMatchExtractedNumbers = null;
return returning;
}
public WSocServer(int port){
super(new InetSocketAddress(port));
}
public WSocServer(InetSocketAddress address) {
super(address);
}
#Override
public void onOpen(WebSocket conn, ClientHandshake handshake) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
Log.i("WebSocket(open)", conn.getRemoteSocketAddress().getAddress().getHostAddress() + " entered the room!");
logs.add(conn.getRemoteSocketAddress().getAddress().getHostAddress() + " entered the room!");
matchUsers = new ArrayList<>();
matchUsers.addAll(Arrays.asList("user1","user2","user3","user4","user5"));
}
});
thread.start();
}
#Override
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
Log.i("WebSocket(close)", conn + " has left the room! Reason: " + reason);
logs.add(conn + " has left the room!");
}
});
thread.start();
}
#Override
public void onMessage(WebSocket conn, String message) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
logs.add(message + " from " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
Log.i("WebSocket(message)", conn + ": " + message);
MainActivity.addOnView();
if(message.startsWith("username")){
if(matchUsers.size() < 6){
String user = message.replace("username;","");
if(!matchUsers.contains(user)) {
matchUsers.add(user);
clientConnection.put(user,conn);
}
String sending = "matchUsers;" + UsersListToString(matchUsers);
conn.send(sending);
}
else conn.send("errorUsername");
}
else if(message.equals("timerStart")){
initTimer();
if(matchUsers.size() < 6){
String sending = "timeStarter;" + timerSeconds.toString();
conn.send(sending);
}
else conn.send("errorTimer");
}
else if(message.equals("getMatchId")){
if(!matchUsers.isEmpty()){
initMatch();
matchUsers.clear();
}
String sending = "matchId;" + matchId.toString();
conn.send(sending);
}
else if(message.startsWith("inGame")){
String[] fields = message.split(";");
String matchId = fields[1].split("=")[1];
int turn = Integer.parseInt(fields[2].split("=")[1]);
Integer extraction = getExtractedNumber(matchId,turn);
fields = null;
conn.send("extracted=" + extraction.toString());
}
else if(message.startsWith("score")){
String matchId = message.split(";")[1].split("=")[1];
String score = message.split(";")[0].split("=")[1];
WebSocket[] clients = matchClients.get(matchId).toArray(new WebSocket[0]);
String user = "";
Enumeration<String> keys = clientConnection.keys();
String key = keys.nextElement();
while(!key.isEmpty()){
if(clientConnection.get(key) == conn) {
user = key;
break;
}
key = keys.nextElement();
}
keys = null;
Hashtable<String,ArrayList<String>> tmp = users_scorePerMatch.get(matchId);
ArrayList<String> tmp_list = tmp.get(user);
tmp_list.add(score);
tmp.replace(user,tmp_list);
users_scorePerMatch.replace(matchId,tmp);
for(int i = 0; i < clients.length; i++){
clients[i].send("statement;" + user + " got " + score + " with");
}
clients = null;
}
else if(message.startsWith("endMatchData")){
String matchId = message.split(";")[1].split("=")[1];
Hashtable<String,ArrayList<String>> users_ofMatch = users_scorePerMatch.get(matchId);
ArrayList<String> users = new ArrayList<>();
Enumeration<String> e = users_ofMatch.keys();
while(e.hasMoreElements()){
Log.e("endmatchdata","a");
users.add(e.nextElement());
}
e = null;
String sending = "matchEndData;";
for(String user: users) sending += user + "=" + UsersListToString(users_ofMatch.get(user)) + ":";
users_ofMatch = null;
conn.send(sending);
}
else if(message.startsWith("totalEnd")){
String matchId = message.split(";")[1].split("=")[1];
if(matchClients.get(matchId)!=null) {
WebSocket[] clients = matchClients.get(matchId).toArray(new WebSocket[0]);
for (WebSocket client : clients) client.close();
Enumeration<String> e = clientConnection.keys();
boolean exit = false;
while (e.hasMoreElements() && !exit) {
Log.e("totalend", "while");
for (WebSocket client : clients) {
Log.e("totalend", "for");
String tmp = e.nextElement();
if (clientConnection.get(tmp) == client) {
clientConnection.remove(tmp);
exit = true;
break;
}
}
}
e = null; clients = null;
matchClients.remove(matchId);
users_scorePerMatch.remove(matchId);
matchExtractedNumbers.remove(matchId);
}
}
}
});
thread.start();
}
#Override
public void onMessage(WebSocket conn, ByteBuffer message) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
Log.i("WebSocket(message)", conn + ": " + message );
}
});
thread.start();
}
public static void main(String[] args){
}
#Override
public void onError(WebSocket conn, Exception ex) {
ex.printStackTrace();
}
#Override
public void onStart() {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
Log.i("WebSocket", "Server started!");
}
});
thread.start();
}
}
}
EDIT: The thing seems to be happening at the end of the match(i.e in the message.startsWith("totalEnd") or message.startsWith("endmatchdata") if cases in the onMessage method
EDIT 2: I found out that the addOnView function was badly written.
I changed it into
private static void addOnView(){
ConstraintLayout cl = binding.logsView;
Handler h = new Handler(Looper.getMainLooper());
final TextView tv = new TextView(binding.getRoot().getContext());
tv.setTextSize(16);
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
tv.setPadding(40,180*(logs.size()+1),40,0);
tv.setText(logs.get(logs.size()-1));
Runnable r = new Runnable() {
#Override
public void run() {
cl.addView(tv);
}
};
h.post(r);
h = null;
r = null;
}
And it solved.

ScrollView doesn't scroll programmatically in a Thread

So what i want to do basically is to scroll the scroll view as the client app sends the command. The method handleScrolling() works in the onCreate() but whenever i call it from the Thread, it doesn't scroll. I think that calling it from the Thread is the problem.
public class TeleprompterActivity extends Activity {
static ScrollView mScrollView;
TextView teleprompterTextView;
String message;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_teleprompter);
teleprompterTextView = findViewById(R.id.teleprompter_text_view);
teleprompterTextView.setText(MainActivity.contents);
mScrollView = findViewById(R.id.scroll);
Thread mThread = new Thread(new ServerClass());
mThread.start();
handleScrolling(3, true);
Log.e("TELE", "handleScrolling at start onCrete");
}
void handleScrolling(final int numLines, final boolean next) {
mScrollView.post(new Runnable() {
public void run() {
int currPosition = mScrollView.getScrollY();
int textSize = (int) teleprompterTextView.getTextSize();
if (next) {
int newPos = currPosition + (textSize * numLines);
mScrollView.smoothScrollTo(0, newPos);
}
if (!next) {
int newPos = currPosition - (textSize * numLines);
if (newPos < 0) {
newPos = 0;
}
mScrollView.scrollTo(0, newPos);
}
}
});
}
void handleMessage(String message) {
if (message.contains("NEXT:")) {
try {
int numLine = Integer.parseInt(message.substring(5));
handleScrolling(numLine, true);
return;
} catch (NumberFormatException nFE) {
nFE.printStackTrace();
Toast.makeText(TeleprompterActivity.this, "Number Format Exception", Toast.LENGTH_SHORT).show();
}
}
if (message.contains("BACK:")) {
try {
int numLine = Integer.parseInt(message.substring(5));
handleScrolling(numLine, false);
} catch (NumberFormatException nFE) {
nFE.printStackTrace();
Toast.makeText(TeleprompterActivity.this, "Number Format Exception", Toast.LENGTH_SHORT).show();
}
}
}
public class ServerClass implements Runnable {
ServerSocket serverSocket;
Socket socket;
DataInputStream dataInputStream;
String receivedData;
Handler handler = new Handler();
#Override
public void run() {
try {
serverSocket = new ServerSocket(8080);
Log.e("TELE", "WAITIN FOR CLIENT");
while (true) {
socket = serverSocket.accept();
dataInputStream = new DataInputStream(socket.getInputStream());
receivedData = dataInputStream.readUTF();
handler.post(new Runnable() {
#Override
public void run() {
message = receivedData;
handleMessage(message);
}
});
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
The handleScrolling() method works perfectly when called outside the Thread. Is it any problem of reference or something like that.
Thanks..
Never update UI components from a thread directly ,call Activity's runOnUiThread so you can use code construct like below:
public class TeleprompterActivity extends Activity {
static ScrollView mScrollView;
TextView teleprompterTextView;
String message;
Activity thisActivity;//<--- used for saving reference to this Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_teleprompter);
teleprompterTextView = findViewById(R.id.teleprompter_text_view);
teleprompterTextView.setText(MainActivity.contents);
mScrollView = findViewById(R.id.scroll);
thisActivity = this;//<---- saving a reference to this activity
Thread mThread = new Thread(new ServerClass());
mThread.start();
handleScrolling(3, true);
Log.e("TELE", "handleScrolling at start onCrete");
}
void handleScrolling(final int numLines, final boolean next) {
thisActivity.runOnUiThread(new Runnable()//<--used thisActivity.runOnUiThread here
{
public void run() {
int currPosition = mScrollView.getScrollY();
int textSize = (int) teleprompterTextView.getTextSize();
if (next) {
int newPos = currPosition + (textSize * numLines);
mScrollView.smoothScrollTo(0, newPos);
}
if (!next) {
int newPos = currPosition - (textSize * numLines);
if (newPos < 0) {
newPos = 0;
}
mScrollView.scrollTo(0, newPos);
}
}
});
}

Handlers don't end after calling removeCallbacksAndMessages(null)

I have two handlers. Handler in a handler. Both of them are in a for-loop.
The overview is something like this,
for{
handler.postDelayed(runnableA{
for{
handler2.postDelayed(runnableB{
function();
}, 3000);
}
}, 1000);
}
I wanted to end handlers' work at any time when the user clicks back button. So, I created two Runnable Classes so that I can use something like runnableA.removellbacksAndMessages(null).
Handler messageHandler;
Handler countDownHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toast.makeText(this, "Start Play in 5 seconds", Toast.LENGTH_SHORT).show();
countDownHandler = new Handler();
for (int i = 7; i >= 0; --i) {
final int idx = i;
Runnable countRunnable = new CountRunnable(idx, countDownView);
countDownHandler.postDelayed(countRunnable, 1000 * (7 - i));
}
}
And this is Runnable Classes.
public class CountRunnable implements Runnable {
int idx;
TextView countDownView;
public CountRunnable(int idx, TextView countDownView) {
this.idx = idx;
this.countDownView = countDownView;
}
#Override
public void run() {
int messageSize = messageItems.size();
for (int j = 0; j < messageSize; j++) {
final int jdx = j;
messageHandler = new Handler();
Runnable messageRunnable = new MessageRunnable(jdx);
messageHandler.postDelayed(messageRunnable, 3000 * jdx);
}
}
}
class MessageRunnable implements Runnable {
int jdx;
public MessageRunnable(int jdx) {
this.jdx = jdx;
}
#Override
public void run() {
addMessageView(messageItems.get(jdx));
}
}
This is onBackPressed():
#Override
public void onBackPressed() {
super.onBackPressed();
Toast.makeText(getApplicationContext(), "All Work Ended.", Toast.LENGTH_SHORT).show();
scrollFlag = true;
try {
messageHandler.removeCallbacksAndMessages(null);
} catch (Exception e) {
Log.d(TAG, "messageHandler never used");
e.printStackTrace();
}
try {
countDownHandler.removeCallbacksAndMessages(null);
} catch (Exception e) {
e.printStackTrace();
}
}
public void addMessageView(String message){
try{
mTextView.setText(message);
}catch(Exception e){
Toast.makeText(getApplicationContext(), "Abnormal End", Toast.LENGTH_SHORT).show();
}
}
But, I keep getting errors because the activity already ended but the handlers can't find the activity. So, Abnormal End Toast message shows as many as the size of inner for loop.
I can ignore this if I don't use the Toast message, but I am afraid of Memory leak or Bad formed Program or something like that.
How can I fix this problem?
The main problem is that you are creating n numbers of CountRunnables and m number MessageRunnables. Despite creating more than one numbers of handlers you are removing callbacks only for the latest-created Hanlder.
Here's what you should do:
Keep a reference of all the Handlers and Runnables and call messageHandler.removeCallbacksAndMessages(null); and countDownHandler.removeCallbacksAndMessages(null); on all of them.

delay inside for loop, make toast every 2 seconds

So hi everyone, this is my first post in stackoverflow,
and i get stucked in 1 problem,
the problem is:
how can I add a delay inside for loop
I did lots of research and none of it works
So I decided to ask myself.
Here is my code
Handler handler1 = new Handler();
for (langId = 1; langId <= 3; langId++) {
handler1.postDelayed(new Runnable() {
#Override
public void run() {
if (langId == 1) {
Toast.makeText(KCRdestActivity.this, "1", Toast.LENGTH_LONG).show();
delayTime += 2000;
}
if (langId == 2) {
Toast.makeText(KCRdestActivity.this, "2", Toast.LENGTH_LONG).show();
delayTime += 2000;
}
if (langId == 3) {
Toast.makeText(KCRdestActivity.this, "3", Toast.LENGTH_LONG).show();
delayTime += 2000;
}
}
}, delayTime);
}
So the result I want is:
"1" -> 2000ms -> "2" -> 2000ms -> "3"
Any ideas?
I tried Thread.sleep(2000), it works, but it freeze the app, I need to do extra things during the process.
Edit
Problem solved, this is the working code, also my final goal
playBtn2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Handler handler1 = new Handler();
langId = 1;
max = 1;
delayTime = 0;
selectedMP = 1;
if (((RadioButton) findViewById(R.id.noneDepart)).isChecked()) max = 3;
else max = 6;
handler1.post(new Runnable() {
#Override
public void run() {
if (((RadioButton) findViewById(R.id.noneDepart)).isChecked()) {
String destdir = "KCR/Depart/" + Utils.getDestID(selectedDest) + "_";
if (viaRAC.isChecked()) destdir = destdir + "via_rac_";
destdir = destdir + langId + ".mp3";
if (selectedMP == 1) {
try {
afd = getAssets().openFd(destdir);
mp1.reset();
mp1.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
mp1.prepare();
mp1.start();
//Utils.RunOnUiThread(KCRdestActivity.this, mp1, sb1);
((Button) findViewById(R.id.Play1)).setText("❙❙");
selectedMP = 2;
delayTime = mp1.getDuration() - 130;
Toast.makeText(KCRdestActivity.this, delayTime + "##" + destdir, Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
afd = getAssets().openFd(destdir);
mp2.reset();
mp2.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
mp2.prepare();
mp2.start();
//Utils.RunOnUiThread(KCRdestActivity.this, mp1, sb1);
((Button) findViewById(R.id.Play1)).setText("❙❙");
selectedMP = 1;
delayTime = mp2.getDuration() - 130;
Toast.makeText(KCRdestActivity.this, delayTime + "##" + destdir, Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}
}
}
if (langId > 3) {
return;
}
langId++;
handler1.postDelayed(this, delayTime);
}
});
}
});
Handler handler1 = new Handler();
int langId = 1;
handler1.postDelayed(new Runnable() {
#Override
public void run() {
if (langId > 3) {
return;
}
if (langId == 1) {
Toast.makeText(KCRdestActivity.this, "1", Toast.LENGTH_LONG).show();
delayTime = 2000;
}
if (langId == 2) {
Toast.makeText(KCRdestActivity.this, "2", Toast.LENGTH_LONG).show();
delayTime = 2000;
}
if (langId == 3) {
Toast.makeText(KCRdestActivity.this, "3", Toast.LENGTH_LONG).show();
delayTime = 2000;
}
langId++;
handler1.postDelayed(this, delayTyme);
}
}
There's no need to write that much lines of code, try this:
Handler handler1 = new Handler();
int langId = 1;
handler1.post(new Runnable() {
#Override
public void run() {
if (langId > 3) {
return;
}
Toast.makeText(KCRdestActivity.this, String.valueOf(langId++), Toast.LENGTH_LONG).show();
handler1.postDelayed(this, 2000); // If delay time is constant!
}
});
you can use asyntask along with Thread.sleep(2000) in the doInBackground method
try this..
MainActivity.....
long Delay = 2000;
oncreate().........
Timer Run = new Timer();
TimerTask Show = new TimerTask() {
#Override
public void run() {
do something.........
}
};
Run.schedule(Show, Delay);
}
You need to move your code out of run method and put into for loop directly. Put only toast inside run method.
1. Implement a timer task and schedule it after every 2seconds
int value = 1;
Timer timer = new Timer();
TimerTask task = new TimerTask() {
#Override
public void run() {
Toast.makeText(KCRdestActivity.this, value, Toast.LENGTH_LONG).show();
value++;
}
};
timer.schedule(task, 2000);
OR
2. Change your code to
Try
for (langId = 1; langId <= 3; langId++) {
delayTime += 2000;
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
Toast.makeText(KCRdestActivity.this, String.valueOf(langId), Toast.LENGTH_LONG).show();
}
}, delayTime);
}
You can use an AsyncTask for this.
public class MyAsyncTask extends AsyncTask<Void, Integer, Void> {
#Override
protected Void doInBackground(Void... params) {
for (int langId = 1; langId <= 3; langId++) {
publishProgress(langId);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
Toast.makeText(KCRdestActivity.this, String.valueOf(values[0]), Toast.LENGTH_LONG).show();
}
}
use this method
declare global these classes
private int TIME_STAMP_INTERVAL = 2000;
private Runnable runnable = null;
private int count=0;
final Handler handler = new Handler();
then add this in method which u call
runnable = new Runnable() {
#Override
public void run() {
Toast.makeText(context, ""count++, Toast.LENGTH_SHORT).show();
handler.postDelayed(runnable, TIME_STAMP_INTERVAL);
}
};
handler.post(runnable);
A quick and dirty way to achieve this using Thread.sleep(2000):
public static void main(String[] args) {
Runnable forLoop = () -> {
for (int i = 1; i <= 3; i++) {
System.out.print(i); // Do your stuff
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
new Thread(forLoop).start();
}
Output:
1 -> 2000ms -> 2 -> 2000ms -> 3

Stuck in a loop, freezing the android app

I found out that when i pressed a button to run a while loop, the android app will freeze although the program can run. It seem that i stuck in a loop and i want to make a thread to show the GUI and the other for the main code . I'm new in java and i'm self-learned so i would appreciated if anyone could give me an example how to prevent the app from freezing.
I'm sorry if i didn't explain my problem well.
Thank you
Here is my code
public class TachoCount extends Thread {
public boolean isConnected;
protected static final String TAG = "TachoCount";
NXTConnector conn;
//_message = (TextView) findViewById(R.id.messageText);
//final TextView textView = (TextView) findViewById(R.id.textView1);
public static NXTConnector connect(final CONN_TYPE connection_type) {
Log.d(TAG, " about to add LEJOS listener ");
NXTConnector conn = new NXTConnector();
conn.setDebug(true);
conn.addLogListener(new NXTCommLogListener() {
public void logEvent(String arg0) {
Log.e(TAG + " NXJ log:", arg0);
}
public void logEvent(Throwable arg0) {
Log.e(TAG + " NXJ log:", arg0.getMessage(), arg0);
}
});
switch (connection_type) {
case LEGO_LCP:
conn.connectTo("btspp://NXT", NXTComm.LCP);
break;
case LEJOS_PACKET:
conn.connectTo("btspp://");
break;
}
return conn;
}
public TachoCount() {
}
public void closeConnection() {
try {
Log.d(TAG, "TachoCount run loop finished and closing");
conn.getNXTComm().close();
} catch (Exception e) {
} finally {
conn = null;
}
}
public void establishConnection(){
conn = TachoCount.connect(CONN_TYPE.LEGO_LCP);
NXTCommand.getSingleton().setNXTComm(conn.getNXTComm());
NXTInfo info = conn.getNXTInfo();
if (info.connectionState== NXTConnectionState.LCP_CONNECTED)
{
isConnected = true;
// set
//textView.setText("NXT is here");
}
}
public void forward(){
Motor.A.setSpeed(300);
Motor.C.setSpeed(300);
Motor.A.forward();
Motor.C.forward();
}
public void backward(){
Motor.A.setSpeed(300);
Motor.C.setSpeed(300);
Motor.A.backward();
Motor.C.backward();
}
public void byebye(){
Motor.A.stop();
Motor.C.stop();
}
public int getSensorValue()
{
int val = 0;
LightSensor ls = new LightSensor(SensorPort.S3);
val = ls.readValue();
return val;
}
public void linefollower()
{
run();
}
public void run()
{
int min = 30, max = 37, readLight = 0, Mspeed = 90, Mspeed2 = 20;
LightSensor ls = new LightSensor(SensorPort.S3);
while(true){
Motor.A.forward();
Motor.C.forward();
readLight = ls.readValue();
LeJOSDroid.sendMessageToUIThread("Sensor: "+ls.readValue());
if (readLight < min){
readLight = min+1;
}
if (max < readLight){
readLight = max-1;
}
Motor.C.setSpeed(Mspeed + (Mspeed2 * (readLight - min)));
Motor.A.setSpeed(Mspeed + (Mspeed2 * (max - readLight)));
}
}
i tried to change the code. It runs well (although the reading of the
sensor doesn't seem accurate), but then when i push another button,
nothing happens
public void linefollower()
{
Thread thread = new Thread(runnable);
thread.start();
}
Runnable runnable = new Runnable ()
{
public void run(){
int min = 30, max = 37, readLight = 0, Mspeed = 90, Mspeed2 = 20;
LightSensor ls = new LightSensor(SensorPort.S3);
while(true){
Motor.A.forward();
Motor.C.forward();
readLight = ls.readValue();
LeJOSDroid.sendMessageToUIThread("Sensor: "+ls.readValue());
if (readLight < min){
readLight = min+1;
}
if (max < readLight){
readLight = max-1;
}
Motor.C.setSpeed(Mspeed + (Mspeed2 * (readLight - min)));
Motor.A.setSpeed(Mspeed + (Mspeed2 * (max - readLight)));
}
}
};
Try using Runnable or background worker
Your loop looks infinite, it's always true. Also, it's probably better to do heavy tasks in an asynctask activity.
Check the official info: http://developer.android.com/reference/android/os/AsyncTask.html

Categories

Resources