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
Related
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.
Don't look at all of my code, just the wait() and notify() methods I need to pause the run() method after the loop has finished its work and resume it in the onButtonClick() class, but when I do this I get an exception: current thread is not owner. How do I implement what I wrote in the title of the question
private boolean isFirstPage;
private CommandContext ctx;
private ArrayList<String> linkQuestion;
private Message message;
private int page;
public QuestionListThreads(boolean isFirstPage, CommandContext ctx, ArrayList<String> linkQuestion, Message message) {
this.isFirstPage = isFirstPage;
this.ctx = ctx;
this.linkQuestion = linkQuestion;
this.message = message;
}
#Override
public void run() {
synchronized (this) {
EmbedBuilder eb = new EmbedBuilder();
if (isFirstPage) {
for (; page < 3; page++) {
eb.addField("page " + page, "[link]" + linkQuestion.get(page), false);
}
ctx.getChannel().sendMessage(eb.build()).setActionRow(Button.secondary("next", "next")).queue();
} else {
page = 3;
for (int i = 0; i < 3; i++, page++) {
eb.addField("page " + page, "[link]" + linkQuestion.get(page), false);
if (i == 2) {
message.editMessage(eb.build()).setActionRow(Button.secondary("next", "next")).queue();
try {
this.wait();
i = 0;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
public void onButtonClick(ButtonClickEvent event) {
if (event.getComponentId().equals("next")) {
new QuestionListThreads(false, null, QuestionListCommand2.getLinkQuestion(),
event.getMessage()).notify();
}
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 have a small, but very strange problem...
I need to read fragments from file and place them into array, which is out of reading thread, but when i wants to get them from current thread, i'm getting empty arrray.
My brain crashed at this stuff:
private int fragmentSize = 262144, fragmentCacheElements = 32, fragmentCacheUpdates = 0;
// Cache 8Mb (265Kb*32)(262144*32)
private String[] fragmentCache;
private boolean needCacheUpdate, end;
private Thread cacheThread = new Thread(new Runnable()
{
String[] fCache = new String[fragmentCacheElements];
#Override
public void run()
{
while (!end) {
for (int i = 0; i < fragmentCacheElements; ++i) {
fCache[i] = new String(loadFragment(i + fragmentCacheUpdates * fragmentCacheElements));
}
while (true) {
if (needCacheUpdate) {
++fragmentCacheUpdates;
fragmentCache = fCache;
// fragment[0] != null
needCacheUpdate = false;
break;
}
}
}
}
});
public static void main(String[] args)
{
fragmentCache = new String[fragmentCacheElements];
cacheThread.start();
updateCache();
// Notifying client
}
// Getting fragment from cache to send it to client
// AND WHY fragment[0] == null ???
private String getCache(int id)
{
if (id >= fragmentCacheUpdates * fragmentCacheElements) {
updateCache();
}
return fragmentCache[id - (fragmentCacheUpdates - 1) * fragmentCacheElements];
}
private void updateCache()
{
needCacheUpdate = true;
while (true) {
if (!needCacheUpdate) {
break;
}
}
}
Any suggestions?
Try
fragmentCache = Arrays.copyOf(fCache, fCache.length);
I'm writing code in two different classes. The first one runs IOIO Thread which reads pins status of an IOIO board; when this thread is running, it will update the several TextViews which are on the other class (Tab3Activity.java).
I called the method to update the UI just like the code below.
Tab3Activity.setText(index,"string here");
the setText() above need to be static otherwise it gives an err
Cannot make a static reference to the non-static method setText(int, String) from the type Tab3Activity
The problem is on the Tab3Activity.java.
public static void setText(final int idx,final String str) {
runOnUiThread(new Runnable() {
#Override
public void run() {
_textview[idx].setText(str);
}
});
}
the runOnUiThread above gives an err.
Cannot make a static reference to the non-static method runOnUiThread(Runnable) from the type Activity
This is the IOIO Thread code written in Globalioio.java, i'm trying to update the UI on the Tab3Activity.java. Look at the Loop() method.
class Looper extends BaseIOIOLooper {
#Override
public void setup() throws ConnectionLostException {
//setup DigitalOutputs, AnalogInputs etc here.
if(Tab2Activity.isOpened==true){
led_ = ioio_.openDigitalOutput(0, true);
pwm1S = ioio_.openPwmOutput(10, 100);
pwm1S.setDutyCycle((float)Tab2Activity.pwm1Speed.getProgress()/100);
pwm1Move = ioio_.openDigitalOutput(11, false);
pwm2S = ioio_.openPwmOutput(12, 100);
pwm2S.setDutyCycle((float)Tab2Activity.pwm2Speed.getProgress()/100);
pwm2Move = ioio_.openDigitalOutput(13, false);
pwmSrvo1 = ioio_.openPwmOutput(26, 100);
pwmSrvo1.setDutyCycle((float)Tab2Activity.servo1.getProgress()/100);
pwmSrvo2 = ioio_.openPwmOutput(27, 100);
pwmSrvo2.setDutyCycle((float)Tab2Activity.servo2.getProgress()/100);
}
if(Tab3Activity.isOpened==true){
sensor1 = ioio_.openAnalogInput(41);
sensor2 = ioio_.openAnalogInput(42);
for(int i = 0;i<30;i++){
dInput[i] = ioio_.openDigitalInput(DIGITAL_SENSOR_PIN[i]);
}
for(int i = 0; i<10;i++){
aInput[i] = ioio_.openAnalogInput(ANALOG_SENSOR_PIN[i]);
}
}
connStatus=true;
}
#Override
public void loop() throws ConnectionLostException {
try {
if(Tab3Activity.slideDrawer2.isOpened()==true){
final float range1 = (float)(2914/(sensor1.read() * 675.18+5))-1;
Tab3Activity.setSeekBarSensor(0,(int) (range1));
Tab3Activity.setTextSensor(0,Float.toString((range1)));
final float range2 = (float)(2914/(sensor2.read() * 675.18+5))-1;
Tab3Activity.setSeekBarSensor(1,(int) (range2));
Tab3Activity.setTextSensor(1,Float.toString(range2));
}
if(Tab3Activity.slideDrawer1.isOpened()==true){
if(Tab3Activity.pinsGroup==0){
int idx =0;
for(int i = 0;i<10;i++){
final boolean readingD = dInput[i].read();
if(readingD==true){
Tab3Activity.setSeekBar(idx,(int) (100));
}else{
Tab3Activity.setSeekBar(idx,(int) (0));
}
Tab3Activity.setText(idx,Boolean.toString(readingD));
idx++;
}
}else if(Tab3Activity.pinsGroup==1){
int idx =0;
for(int i = 10;i<20;i++){
final boolean readingD = dInput[i].read();
if(readingD==true){
Tab3Activity.setSeekBar(idx,(int) (100));
}else{
Tab3Activity.setSeekBar(idx,(int) (0));
}
Tab3Activity.setText(idx,Boolean.toString(readingD));
idx++;
}
}else if(Tab3Activity.pinsGroup==2){
int idx=0;
for(int i = 20;i<30;i++){
final boolean readingD = dInput[i].read();
if(readingD==true){
Tab3Activity.setSeekBar(idx,(int) (100));
}else{
Tab3Activity.setSeekBar(idx,(int) (0));
}
Tab3Activity.setText(idx,Boolean.toString(readingD));
idx++;
}
}else if(Tab3Activity.pinsGroup==3){
int idx=0;
for(int i = 0;i<10;i++){
final float readingA = aInput[i].read();
Tab3Activity.setSeekBar(idx,(int) (readingA * 100));
Tab3Activity.setText(idx,Float.toString((readingA * 100)));
idx++;
}
}
}
Thread.sleep(10);
} catch (InterruptedException e) {
ioio_.disconnect();
} catch (ConnectionLostException e) {
throw e;
}
}
}
#Override
public IOIOLooper createIOIOLooper(String arg0, Object arg1) {
// TODO Auto-generated method stub
return new Looper();
}
Is there any alternative to do this?
please give the simple one, i'm quite new to android. Thanks in advance
If this thread is started from the same activity
then you can pass the reference of the activity to the thread, and remove static from that method.
YourThread thread = new YourThread(yourActivity);
thread.start();
//YourThread
public class YourThread extends Thread
{
Tab3Activity activity;
public YourThread(Tab3Activity activity)
{
Tab3Activity.activity = activity;
}
...
activity.setText(index,"string here");
...
}
Note: Make sure your activity has android:configChanges="orientation|keyboardHidden|screenSize". Otherwise as you rotate your devices there will be a new instance of acitivity started.
And if your activity is not starting that thread
then you should not try to access the activity directly through a static method.
If you are sure about your implementation and if it does not lead to a memory leak or crash then try this
Create a static MainLooper Handler in your activity or anywhere.
public static Handler UIHandler = new Handler(Looper.getMainLooper());
now you can use this handler to run on ui thread.
public static void setText(final int idx,final String str) {
UIHandler.post(new Runnable() {
#Override
public void run() {
_textview[idx].setText(str);
}
});
}
Yes there is,
you are coupling between your Thread and the Activity which is not a good design ,
instead use Intent when the Thread finish the I/O fire Intent and catch this inside the activity