I am writing n android app as part of my thesis and need to display/update/append data onto an android screen during a timer event - as follows:
(please excuse possible incorrect terminology and feel free to correct it)
I have a few classes in the app, however am trying to interact between "BlueActivity" and "BuzzActivity".
"BlueActivity" controls blue tooth. It turns on/off blue tooth,makes a connection and controls the socket.
"BuzzActivity" has a button "BUZZME": onClick, BuzzActivity passes (behind the sceens) into "BlueActivity" which sends a packet to the paired device (devDuino, who then radios out to a wearable device. the wearable device radios a reply of data readings back to devDuino). The paired device then replies this data back to "BlueActivity" which is read in through the socket listening on a timer. The data is in the format of a string and is called "retstr". The timer is started in "BlueActivity's" OnCreate() method.
I need to get "retstr" from "BlueActivity" into "BuzzActivity" and updating on the screen.
I have tried .setText and failed in the sense of App crashing. From research i hear about needing a handler to "dynamically" update the view?
Can some one please clarify this.
Code segments as follows:
BlueActivity:
.........//stuff here
//final String TAG = "On create";
new Timer().schedule(new TimerTask() {
#Override
public void run() {
//Log.i(TAG, "In timer running");
String retstr;
retstr = mConnectThread.listen(); //Method to get my data from bluetooth packet
//String text = String.valueOf(retstr); //failed attempts
//BuzzActivity.DivingData.setText(text);
Log.i(TAG, "retstr"); //Works like a charm to print out to log cat
}
}, 1000, 1000);
mConnectThread = new ConnectThread(mmDevice);
mConnectThread.start();
}
BuzzActivity
.......//blueConnecter is called from the .xmlfile controling the buzz button "on click method"
public void blueConnecter(View view){
DivingData = (TextView) findViewById(R.id.DivingDataTextField);
BlueActivity.visible(view);
}
Thanks for any help in advance.
Emma.
Is there a stack trace in the logcat output? You'll probably find that you are trying to update the UI thread from another thread. If that is the case, you need to update that view with runOnUiThread(). Here's an example:
runOnUiThread(new Runnable() {
public void run() {
DivingData.setText(newText);
}
});
Related
This question is very similar to questions that have been asked in the past but please bear with me as it is still a unique question. Basically, I have a class that gets application permissions, and if the user does not have internet running, then when the auto login screen comes, it is stuck in loading. So what I want to do is show a dialog message, and the user will click ok to close the app. For dialogs, I need the context, and I must run on the main thread. I have posted an image of the code because I want to show you that runOnUIThread is red. Here is the error I get form Android Studio
Cannot resolve method runOnUIThread.
Here is what I had
Problem: For some reason, runOnUIThread is not usable. Does anyone have a counter proposal, or a reason as to why I am having this problem?
Here is the code:
public void alert() {
new Thread()
{
public void run()
{
application.runOnUiThread(new Runnable() // application is the context of my current activity.
{
public void run() //I display my alert Dialog here.
{
AlertDialog build= new AlertDialog.Builder(application.getApplicationContext())
.setTitle("Error")
.setMessage("Sorry there seems to be a problem with the service. Please check to make sure you have a stable internet connection. ")
.setPositiveButton("Ok, I understand.", (dialog, which) -> System.exit(0))
.show();
build.setCancelable(false);
Button positive= build.getButton(DialogInterface.BUTTON_POSITIVE);
positive.setTextColor(application.getResources().getColor(R.color.buttonPrimaryColor));
positive.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
}
});
}
}.start();
Here is how I have made it work with a Toast in the past.
public void shortToast(String msg) {
Observable.just(msg)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(message -> {
Toast.makeText(application, message, Toast.LENGTH_SHORT).show();
});
}
// In the main method
shortToast("Sorry an error occured");
For some reason, runOnUIThread is not usable
The method that you are trying to invoke is runOnUiThread(). That is a method on Activity. Whatever application is, it is not an Activity.
Does anyone have a counter proposal
Move this code into an Activity. Generally, pop-ups (dialogs, snackbars, etc.) should be displayed by an Activity. And only an Activity can show a Dialog, such as an AlertDialog.
Try to use an activity to run on UI, not application
So I am creating an app where I get the string from my AsyncTask which I have created as a subclass in my MainActivity class in order to get the variables I receive from the internet. And according to variables I get I change the images accordingly after every 5 seconds. Now the task is successful but on activity refresh I keep getting the default layout I created in activity_main.xml and again it changes to the one I want.
Posting my code below.
Thread thread = new Thread() { //thread I am running every 5 secs
#Override
public void run() {
try {
synchronized (this) {
wait(5000);
syncapp sa = new syncapp(); //AsyncTask to get String from Internet
sa.execute();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
Intent mainActivity = new Intent(getApplicationContext(), MainActivity.class); //Creating intent to restart the activity (Need a workaround if possible)
startActivity(mainActivity);
}
;
};
thread.start();
}
public void setImage(String str) //Function I will call to change Image
{
vacancy =0;
b = a.toCharArray();
for (int i = 0; i < 6; i++)
if (b[i] == '0'){
iv[i].setImageResource(R.drawable.img2);
vacancy++;}
else if (b[i] == '1') {
iv[i].setImageResource(R.drawable.img1);
}
Log.i("abc ", a);
tv.setText("InBackGround" + str);
}
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
/* for(int i =0;i<6;i++) {
outState.putChar("imv"+(i+1), b[i]);
}*/
outState.putString("a",a); //Getting a from the internet (php file)
Log.i("Saved State", "Activity A - Saving instance state");
}
Now what I want is if you have a better method to do this thing. Eg. In a Stock market application the prices keep on changing. The same way I want my image to change according to the data I get.
If this is the only method then how do I save changes I make
(eg. like in the code above setImageResource to img2) permanently.
If I can use something else ImageView.
I have already used onSaveInstanceState But as I am taking values from the internet I don't know I am not able to use them.
So first of all.. when working with UI elements such as Views, Widgets, you would want to avoid spawning your own threads, as View can be touched only from the thread it was created from.
Second.. you would also want to avoid sleeping inside your worker thread - basically just use the Handler class (from android.os) and post a delayed Runnable, like so: https://stackoverflow.com/a/20784353/2102748. Just be sure to stop all work on that particular handler when your Activity stops, like so: https://stackoverflow.com/a/3627399/2102748
Third - you should perhaps load the photo immediately (on the same AsyncTask or thread) if that is the only thing you need, but be sure to post the "set bitmap to view" work to the handler you created.
Hope this helps.
When I run this code on a real device the ad-banner pops up endless times. How should i modifiy this code to run it just once?
This code is from a game. Every time the player gets hit by something he loses 1 shield.
private void showBanner() {
adView.setVisibility(View.VISIBLE);
adView.loadAd(new AdRequest.Builder()
.addTestDevice(AdRequest.DEVICE_ID_EMULATOR).build());
}
if (player.getShieldStrength() == 0){
runOnUiThread(new Runnable() {
#Override
public void run() {
showBanner();
}
});
}
This my logcat:
Aborting last ad request since another ad request is already in progress.
The current request object will still be cached for future refreshes.
...
This runnable is triggered by the run method. showBanner is part of update-method
#Override
public void run() {
while (playing) {
update();
draw();
control(); }}
You are confused.
A banner ad is not like an interstitial. It does not pop-up.
When you request a banner ad you are requesting ads to fill that AdView until you tell it to stop or you hide it. It will show new ads on the refresh cycle you have configured in the Admob dashboard. It will not show a single ad.
If you really only want a banner ad to be shown until the next game, then call adView.setVisible(VIEW.INVISIBLE) or adView.setVisible(VIEW.GONE)
And please don't repost existing questions Ad pops up multiple times
I have been using an emulator with the following code to press a particular button
redBut.performClick();
redBut.setPressed(true);
redBut.invalidate();
redBut.setPressed(false);
redBut.invalidate();
Using Log statements, I know for sure this piece of code is being called, so it is not that the code is being skipped over.
On my emulator, the button appeared to be pressed as if a user pressed it. Now on a real android device, the process is running but the button is unchanged. What is the problem?
Write your code as follows-
redBut.performClick();
redBut.setPressed(true);
redBut.invalidate();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
redBut.setPressed(false);
redBut.invalidate();
}
}, 500);
I am creating application which works with SMS service and FTP networking.
If user does not establish connectivity, it will try to reconnect again in 30 seconds.
I am using CountDownTimer with TextView to inform user about time left to reconnnect.
Either it will be successful or it will start counting again.
My problem is, that if counter restarts while activity is in background or the screen is locked, TextView keeps showing number "1" (it won't update) until the timer restarts again in foreground (but updating numbers without timer restart works fine in backround or lock, I am using wakelock in my foreground service).
After counter restarts again (so it won't stop counting) while application is in foreground, everything comes back to normal, TextView updates from freezed "1" to "30" and starts counting down to "1".
I think problem will be somewhere in communication between counter thread and background activity with UI, but I don't know nothing more about it.
I tried several things like:
creating setter and getter for miliseconds and update them in each
tick, then try to update textview from onReume(), didn't work.
create local variable for TextView inside timer, initialize it inside onTick() and
try to update text from there, also didn't work.
Thanks everyone for help, I will appriciate any advices.
Part of code relative to question:
private CountDownTimer cdt = null;
private final TextView getTextView_ActivityMainMenu_Timer(){
return (TextView) findViewById(R.id.ActivityMainMenu_TextView_Timer);
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getBooleanExtra("KEY_FAILED", false)){
cdt = new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
getTextView_ActivityMainMenu_Timer().setText("" + millisUntilFinished / 1000);
}
public void onFinish() {
;
}
}
.start();
}
else
{
if(cdt != null)
cdt.cancel();
}
}
};
Finally I found solution of this problem. I didn't realize that I am unregistering the receiver in onPause() method. So I had to change it and put registration of broadcast into onResume() and unregister it only in onDestroy() method.