i don't understand why i get different Id for the same thread here is the output
i know the id field in any programming language must stay the same for future reference
PS:this code is inside a bound service class i know the bound service is on the main thread but why id of the "message thread" changed 3 times from -1 to 21947 to 41045
*logcat output:
onCreate: thread id = 1 name =main
first is alive true thread id -1 thread name =servicemessanger
sec is alive true thread id 21947 thread name =servicemessanger
handleMessage: thread id= 41045name = servicemessanger*
code :
#Override
public void onCreate() {
Log.i(TAG, "onCreate: thread id = "+ Thread.currentThread().getId()+" name =" +Thread.currentThread().getName() );
super.onCreate();
HandlerThread thread = new HandlerThread("servicemessanger");
thread.start();
Log.i(TAG, " first is alive "+thread.isAlive() + " thread id "+ thread.getThreadId()+ " thread name ="+thread.getName());
mHandler = new Handler(thread.getLooper()){
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.i(TAG, "handleMessage: thread id= "+Thread.currentThread().getId()+"name = " + Thread.currentThread().getName());
}
};
mHandler.sendEmptyMessage(0);
Log.i(TAG, " sec is alive "+thread.isAlive() + " thread id "+ thread.getThreadId()+ " thread name ="+thread.getName());
}
thank you,
Related
I decided to use intent service for a task involving looping big number of results, calculating a summary result and inserting it back in firestore.
This is how i am calling my intent service from activity.
onDataSnapShotListenerForPointsAndRating = db.collection("PointsAndRating")
.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot queryDocumentSnapshots,
#Nullable FirebaseFirestoreException e) {
Intent serviceIntent = new Intent(PlayWithMrMathActivitySinglePlayer.this,
MyIntentService.class);
serviceIntent.putExtra("SENDER", "Mr. Math");
serviceIntent.putExtra("emailAddress", emailAddress);
serviceIntent.putExtra("OwnID", OwnID);
Log.d(TAG, "Hello MyIntentService: I am Mr Math and i am starting service");
**startService(serviceIntent);**
}
});
This is how I am doing that big loop work:
#Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "onHandleIntent: inside onHandleIntent ");
String sender = intent.getStringExtra("SENDER");
emailAddress = intent.getStringExtra("emailAddress");
OwnID = intent.getStringExtra("OwnID");
Log.d(TAG, "onHandleIntent: inside onHandleIntent sender = " + sender);
Log.d(TAG, "onHandleIntent: inside onHandleIntent emailAddress = " + emailAddress);
Log.d(TAG, "onHandleIntent: inside onHandleIntent OwnID = " + OwnID);
Log.d(TAG, "onDataSnapShotListenerForPointsAndRating: ");
Log.d(TAG, "onHandleIntent: currentThread = " + Thread.currentThread().getId());
db.collection("PointsAndRating")
.orderBy("gmq", Query.Direction.DESCENDING)
.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot>task) {
Long myWorldRank = new Long(0);
Log.d(TAG, "onComplete: onDataSnapShotListenerForPointsAndRating = " + task.getResult().size());
if (task.isSuccessful()) {
Log.d(TAG, "onHandleIntent InonComplete : If currentThread = " + Thread.currentThread().getId());
for (QueryDocumentSnapshot document: task.getResult()) {
Log.d(TAG, document.getId() + "= onDataSnapShotListenerForPointsAndRating =## => " + document.getData());
myWorldRank = myWorldRank + 1;
if (document.getId().equals(emailAddress)) {
break;
}
***Log.d(TAG, "onHandleIntent InonComplete : For Loop currentThread = " + Thread.currentThread().getId());***
} // end of for loop
Log.d(TAG, "onDataSnapShotListenerForPointsAndRating: Rank = " + myWorldRank);
}
final Map<String, Object> myWorldRankUpdateNugget = new HashMap<>();
myWorldRankUpdateNugget.put("myWorldRank", myWorldRank);
db.collection("PointsAndRating")
.whereEqualTo("userID", OwnID)
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document: task.getResult()) {
db.collection("PointsAndRating")
.document(document.getId())
.set(myWorldRankUpdateNugget, SetOptions.merge())
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Log.d(TAG, "onDataSnapShotListenerForPointsAndRating: WORLD RANK UPDATED ");
}
});
} // end of for loop
}
Log.d(TAG, "onHandleIntent: EXIT currentThread = " + Thread.currentThread().getId());
}
});
}
});
} // end of onhandle
and i see this in logs.
06-28 17:48:34.068 11076-11154/com.udiversity.myapplication D/MyIntentService: onHandleIntent: currentThread = 3867
06-28 17:49:36.118 11076-11076/com.udiversity.myapplication D/PlayWithMrMathActivitySinglePlayer: onCreate: currentThread = 1
06-28 17:49:36.118 11076-11076/com.udiversity.myapplication D/PlayWithMrMathActivitySinglePlayer: OnSubmitPOC: currentThread Back Home OnCreate
06-28 17:49:36.118 11076-11106/com.udiversity.myapplication D/PlayWithMrMathActivitySinglePlayer: doInBackground: currentThread = 3837
06-28 17:49:36.148 11076-11076/com.udiversity.myapplication D/PlayWithMrMathActivitySinglePlayer: onProgressUpdate currentThread = 1
06-28 17:49:36.158 11076-11076/com.udiversity.myapplication D/PlayWithMrMathActivitySinglePlayer: onProgressUpdate EXIT 1 currentThread = 1
06-28 17:49:48.328 11076-11076/com.udiversity.myapplication D/MyIntentService: onHandleIntent InonComplete : If currentThread = 1
06-28 17:49:48.328 11076-11076/com.udiversity.myapplication D/MyIntentService: onHandleIntent InonComplete : For Loop currentThread = 1
06-28 17:49:48.328 11076-11076/com.udiversity.myapplication D/MyIntentService: onHandleIntent InonComplete : For Loop currentThread = 1
06-28 17:49:48.328 11076-11076/com.udiversity.myapplication D/MyIntentService: onHandleIntent InonComplete : For Loop currentThread = 1
06-28 17:49:48.328 11076-11076/com.udiversity.myapplication D/MyIntentService: onHandleIntent InonComplete : For Loop currentThread = 1
06-28 17:49:48.338 11076-11076/com.udiversity.myapplication D/MyIntentService: onHandleIntent InonComplete : For Loop currentThread = 1
06-28 17:49:48.338 11076-11076/com.udiversity.myapplication D/MyIntentService: onHandleIntent InonComplete : For Loop currentThread = 1
06-28 17:49:48.338 11076-11076/com.udiversity.myapplication D/MyIntentService: onHandleIntent InonComplete : For Loop currentThread = 1
06-28 17:49:48.338 11076-11076/com.udiversity.myapplication D/MyIntentService: onHandleIntent InonComplete : For Loop currentThread = 1
06-28 17:49:48.338 11076-11076/com.udiversity.myapplication D/MyIntentService: onHandleIntent InonComplete : For Loop currentThread = 1
06-28 17:49:48.338 11076-11076/com.udiversity.myapplication D/MyIntentService: onHandleIntent InonComplete : For Loop currentThread = 1
06-28 17:49:48.338 11076-11076/com.udiversity.myapplication D/MyIntentService: onHandleIntent InonComplete : For Loop currentThread = 1
06-28 17:49:48.338 11076-11076/com.udiversity.myapplication D/MyIntentService: onHandleIntent InonComplete : For Loop currentThread = 1
Why this loop inside onHandleIntent->db.Collection("").get().onComplete() is running on main thread ?
public class MyIntentService extends IntentService {
private static final String TAG = "MyIntentService";
FirebaseFirestore db = FirebaseFirestore.getInstance();
db is my local class database instance.
At the beginning of onHandleIntent you use Thread.currentThread().getId() in order to get the thread's ID. It is logged as 3867. Inside the onComplete method you log again the thread ID and you get 1.You also log the thread ID of the nested onComplete, but it doesn't look like it has been added to the provided logs.
The thread IDs of the should-be-different threads are different and thus the code is being executed asynchronously. I'm unsure of what error do you see, but if what worries you is that the ID number is 1, according to the documentation the ID of a thread is unique only during its lifetime when a thread is terminated it may be reused again.
Actually in the provided logs we can see that the thread ID 1 is being used by PlayWithMrMathActivitySinglePlayer but is terminated right before being used by MyIntentService.
Apart from that I don't see anything strange. What is making you believe that there's an error on the code or its execution?
I am creating a text file with data related to my App's game.
I want to show the score at each second in the game.
How can I ensure that my int for seconds is updated, starting at zero
Example of output wanted:
Seconds Score
0 3
1 9
2 16
3 20
.....etc
Current output (seconds always 0):
Seconds Score
0 3
0 9
0 16
0 20
.....etc
Current code:
int seconds=0;
//creating header in the txt file Note: Blanked out as it is generating every second
writeToFileEEGPower(order("Seconds")+order("highAlpha")+order("lowAlpha")+order("highBeta")+order("LowBeta")+
order("lowGamma")+order("midGamma")+order("Delta")+order("Theta")+ "\n");
//creating the string to be written to file
String line = order(seconds+"")+order(eegPower.highAlpha+"")+order(eegPower.lowAlpha+"")+order(eegPower.highBeta+"")+
order(eegPower.lowBeta+"")+order(eegPower.midGamma+"")+order(eegPower.delta+"")+order(eegPower.theta+"")+ "\n";
//write the string to file
writeToFileEEGPower(line);
seconds++;
I think you should rather use a sqlite table for this. Greendao
is a good tool for managing those tables. You can save the information every second to a table. When the game is finished, you have a full list of the score for each second of the game.
In your code example the "second" variable is set to 0 each time before you write a new line. I think that is the problem.
Using TimerTask or Handler with postDelayed() method can do the trick.
You can use a handler to update your text file every second:
public class MyActivity extends Activity {
private android.os.Handler mHandler = new android.os.Handler();
private Runnable textFileLogger;
private int seconds = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
//Create header for text file
writeToFileEEGPower(order("Seconds") + order("highAlpha") + order("lowAlpha") + order("highBeta") + order("LowBeta") +
order("lowGamma") + order("midGamma") + order("Delta") + order("Theta") + "\n");
textFileLogger = new Runnable() {
#Override
public void run() {
seconds++;
String line = order(seconds + "") + order(eegPower.highAlpha + "") + order(eegPower.lowAlpha + "") + order(eegPower.highBeta + "") +
order(eegPower.lowBeta + "") + order(eegPower.midGamma + "") + order(eegPower.delta + "") + order(eegPower.theta + "") + "\n";
//write the string to file
writeToFileEEGPower(line);
//Repeats the logging after 1 second
mHandler.postDelayed(this, 1000);
}
};
//Starts the logging after 1 second
mHandler.postDelayed(textFileLogger, 1000);
}
#Override
protected void onDestroy() {
super.onDestroy();
//To stop the logging:
mHandler.removeCallbacks(textFileLogger);
}
}
I trying to build a app on beacons. so I got a sample code from here.
I have run that code and as soon as I entered into range of beacon the app is crashed and error in the logcat is as follow:
06-20 17:48:24.256: E/AndroidRuntime(18104): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
Please help me out.
I checked the code and the error lies in between these lines.
iBeaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<IBeacon> iBeacons, Region region) {
if (iBeacons.size() > 0) {
double distance = iBeacons.iterator().next().getAccuracy();
DecimalFormat decimalFormat = new DecimalFormat("##.##");
double distanceFormatted = Double.valueOf(decimalFormat.format(distance));
TextView distanceTextView = (TextView) findViewById(R.id.am_tv_distance);
distanceTextView.setText(String.valueOf(distanceFormatted) + " m");
}
}
});
You need to perform UI changes in the UI thread:
iBeaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<IBeacon> iBeacons, Region region) {
if (iBeacons.size() > 0) {
double distance = iBeacons.iterator().next().getAccuracy();
DecimalFormat decimalFormat = new DecimalFormat("##.##");
double distanceFormatted = Double.valueOf(decimalFormat.format(distance));
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView distanceTextView = (TextView) findViewById(R.id.am_tv_distance);
distanceTextView.setText(String.valueOf(distanceFormatted) + " m");
}
});
}
}
});
For the CalledFromWrongThreadException,
write a function and call that like:
private void toastToDisplay(final String line) {
runOnUiThread(new Runnable() {
public void run() {
//Toast.makeText(YourActivity.this, "" + line,
// Toast.LENGTH_LONG).show();
TextView yourTextView = (TextView) findViewById(R.id.your_tv);
yourTextView .setText(line);
}
});
}
You can edit that function with your required distanceTextView or other views if you want.
What happens there is that the Service is running on the background thread in your application, so when you directly call an operation that would update the UI, it conflicts with the thread you are in while writing that code.
So If the current thread is not the UI thread, the action is posted to the event queue of the UI thread by using runOnUiThread
What exactly is the meaning of "I am getting only distance not range" ?
...for the iBeacons.iterator().next().getAccuracy();, part.. you can collect the beacon details by using a for each loop like:
for (IBeacon iBeacon : iBeacons) {
String line = "Major: " + iBeacon.getMajor()
+ "Minor: " + iBeacon.getMinor()
+ "Accuracy in m(s): "
+ iBeacon.getAccuracy()
+ "BluetoothAddress: "
+ iBeacon.getBluetoothAddress()
+ "Proximity: " + iBeacon.getProximity()
+ "ProximityUuid: "
+ iBeacon.getProximityUuid() + "Rssi: "
+ iBeacon.getRssi() + "TxPower: "
+ iBeacon.getTxPower();
toastToDisplay(line);
}
In case you haven't already seen it, this Android iBeacon Library sample application is a good reference.
I am having a problem when I create an array of strings, this only happens in 2.1 android api level 7 or lower and i need to install the application on a device with exactly this configuration, any idea how to solve the problem?
Below the source code, the message that pops up on screen and also logcat's message.
CODE:
private String[] fillPedidosName() {
TipoPedidoDAO tipoDAO = null;
try {
tipoDAO = new TipoPedidoDAO();
pedidosList = tipoDAO.selectAll();
String[] temp = new String[pedidosList.size()];
for (int i = 0; i < pedidosList.size(); i++) {
if (pedidosList.get(i) != null) {
temp[i] = pedidosList.get(i).getDescricao().toString();
}
}
return temp;
} catch (Exception ex) {
MyLoger.logar(ex);
return null;
} finally {
if (tipoDAO.getDB().isOpen()) {
tipoDAO.closeConnection();
}
}
}
THE MESSAGE THAT POPS UP DEBUGING:
Exception processing async thread queue
Exception processing async thread queue
java.lang.UnsupportedOperationException
lOGCAT'S MESSAGE:
03-03 17:57:57.124: ERROR/jdwp(1267): REQ: UNSUPPORTED (cmd=2/11 dataLen=8 id=0x0012ba)
You are probably not using a List that supports get(int).
Try changing your List implementation to ArrayList. When you create your list:
List myList = new ArrayList()
This is probably happening inside tipDAO.selectAll().
I had this problem. I got it fixed.
When working with Arrays of your Objects, make sure you have defined a constructor in the object file.
This piece of code was creating the error
List<Prediction> predictions = new ArrayList<Prediction>();
The fix.
Prediction class file was missing a constructor. After putting in a default constructor, the error is gone for me.
package com.thuptencho.torontotransitbus.models;
public class Prediction {
public String epochTime = "", seconds = "", minutes = "", isDeparture = "", affectedByLayover = "", branch = "",
dirTag = "", vehicle = "", block = "", tripTag = "";
//this constructor was missing..after coding this constructor. the error was gone.
public Prediction(){
super();
}
#Override
public String toString() {
return "epochTime:" + this.epochTime + " seconds:" + this.seconds + " minutes:" + this.minutes
+ " isDeparture:" + this.isDeparture + " affectedByLayover:" + this.affectedByLayover + " branch:"
+ this.branch + " dirTag:" + this.dirTag + " vehicle:" + this.vehicle + " block:" + this.block
+ " triptag:" + this.tripTag;
}
}
My problem is that I had a program working before, without threading, and it took a long time to process info (16 seconds to get XML data and display it). Now I've gotten the whole threading and async thing down, but for some reason it is making my program SLOWER (in the emulator, device is not available right now), is there anything I've done that could have caused this, the UI thread is fine, but my async thread takes a minute and a half to execute. (when I had it in the UI thread used to take only 16 seconds, but froze the UI thread)
Here is the code for my thread, it sits inside of the main class:
private class TeamSearchTask extends AsyncTask<String,Void,String> {
CharSequence nfo;
String [] matches;
String [] data;
String teamNum;
ProgressDialog loading;
protected void onPreExecute()
{
//Show the 'loading' dialog
loading = new ProgressDialog(SapphireAlliance.this);
loading.setMessage("Loading, please wait...");
loading.show();
}
protected String doInBackground(String... teamNumber)
{
try
{
//Team information ------------------------------------------------------------------------------------
teamNum = teamNumber[0];
//Array of team data
data = APIconnection.getTeams(teamNum, "");
//Display basic team info
nfo = ("\nFormal Team Name:\n" + data[1] +
"\n\nLocation:\n" + data [3] + ", " + data[4] + ", " + data[5] +
"\n\nRookie Year:\n" + data[6] +
"\n\nRobot Name:\n" + data[7] +
"\n\nWebsite:\n" + data[8] + "\n\n\n\n\n\n\n\n\n");
//Make match archive --------------------------------------------------------------------------------------
String [] events = APIconnection.getEventIdsByYear(year1);
ArrayList<String> matches = new ArrayList<String>();
for (int i = 0; i<events.length; i++)
{
String [] add = APIconnection.getMatches2(teamNum, events[i] ,"","");
for(int j = 0; j<add.length; j++)
matches.add(add[j]);
}
String [] out = new String [matches.size()];
matches.toArray(out);
return "";
}
catch(Exception e)
{
return e.toString();
}
}
protected void onPostExecute(String result) {
if(result.equals(""))
{
info.setText(nfo);
matchArchive(matches);
//title
CharSequence ttl = "Team " + teamNum;
titlets.setText(ttl.toString());
loading.dismiss();
}
else
{
alert.setMessage(result);
alert.show();
}
}
}
Anything in there that could be causing this? :|
It may be that your thread priority may not be set very high. I remember the default is rather low. However, for what you're doing, it shouldn't be taking more than a couple seconds. I would think that the real problem lies in APIconnection going to the network and doing something that takes a long time. Particularly, that for loop that does the event fetching would be doing a lot of work if each call opens a new socket, assuming that this is for FIRST matches. :P
I am having the same issue, doing nothing more than a file copy with simple DES decryption... the whole thing ran in a few seconds on the UI thread, but when moved into an ASYNCTASK it is now taking MINUTES to accomplish. Unbelievable.