TextView not updating after creating new Activity - java

I'm new to Android and I stuck. I have a Textview on Activity which should show result, but for some reason it is updating TextView only if you click on Button which is not doing anything or if you close app and reopen it again from menu of running apps. I suppose it's somehow connected with updating activity. Thank you in advance!
package com.example.visacheck;
import android.content.Intent;
import android.os.Bundle;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class FourthActivity extends AppCompatActivity {
String aplicationNumber;
String type;
String year;
#Override
protected void onCreate(Bundle savedInstanceState) {
this.getSupportActionBar().hide();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fourth);
Intent intent = getIntent();
final Button button = findViewById(R.id.resultButton); //Result appearing only after clicking button
aplicationNumber = intent.getStringExtra("aplicationNumber");
type = intent.getStringExtra("type");
year = intent.getStringExtra("year");
class MyJavaScriptInterface {
#JavascriptInterface
#SuppressWarnings("unused")
public void processHTML(String html) {
TextView text = findViewById(R.id.textView);
text.setText(html);
}
}
final WebView myWebview = findViewById(R.id.webview);
myWebview.getSettings().setJavaScriptEnabled(true);
myWebview.addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT");
myWebview.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
myWebview.loadUrl(("javascript:document.getElementById('edit-ioff-application-number').value = '" + aplicationNumber + "';void(0);"));
myWebview.loadUrl(("javascript:" + "document.getElementById('edit-ioff-application-code').value = '" + type + "';void(0);"));
myWebview.loadUrl(("javascript:document.getElementById('edit-ioff-application-year').value = '" + year + "';void(0);"));
myWebview.loadUrl(("javascript:document.getElementById('edit-submit-button').click();"));
myWebview.loadUrl("javascript:window.HTMLOUT.processHTML(document.getElementsByClassName('alert alert-warning')[0].innerText);");
myWebview.loadUrl("javascript:window.HTMLOUT.processHTML(document.getElementsByClassName('alert alert-success')[1].innerText);");
myWebview.loadUrl("javascript:window.HTMLOUT.processHTML(document.getElementsByClassName('alert alert-danger')[0].innerText);");
}
});
myWebview.loadUrl("https://frs.gov.cz/ioff/application-status");
}
}

I'm not going to do a very good job at this, as I can hardly touch on the subject myself. Maybe someone with more knowledge can go into further detail, but the general idea here is that this code is being called by the JS thread as opposed to your UI thread (Which is the only thread that is allowed to handle UI updates), and I'm surprised this code doesn't crash when doing so, honestly. The post() method adds this to the view's message queue, which means that the text will be updated AFTER the view has been rendered, and has no other tasks to perform. I know I did a bad job at explaining this, but for more information, please refer to these:
What exactly does the post method do?
Alternately, you can user runOnUIThread(), example:
How do we use runOnUiThread in Android?
I'm sure that a lot of people out there have already explained this better than I have. But the most important thing to understand here is that you must not update UI from anything other than the UI thread
Please note that I chose myWebView arbitrarily, and this should work if posted to the fragment's main view aswell.
class MyJavaScriptInterface {
#JavascriptInterface
#SuppressWarnings("unused")
public void processHTML(final String html) {
myWebview.post(new Runnable() {
#Override public void run() {
TextView text = findViewById(R.id.textView); text.setText(html);
}
});
}
}

Related

Java - Web Scraping In Android Studio [duplicate]

This question already has answers here:
Unfortunately MyApp has stopped. How can I solve this?
(23 answers)
Closed 2 years ago.
I'm trying to web scrape from a website https://www.worldometers.info/coronavirus/ and turns that data to form an app but the data is not actually printing I don't the reason but whenever I click the button in an android emulator it just crashes instantly !!
I have 3 textView in the app and a button so whenever I click the button it should show up the data in the textView !!
textView have ids of TotalCases / TotalDeaths / TotalRecovered
button has an id of the button
Here is what I have I have done
package com.example.coronaupdate;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import android.widget.Button;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
Button btn;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
compare();
}
});
}
public void compare()
{
final TextView totalCases;
final TextView totalDeaths;
final TextView totalRecovered;
totalCases = (TextView) findViewById(R.id.TotalCases);
totalDeaths = (TextView) findViewById(R.id.TotalDeaths);
totalRecovered = (TextView) findViewById(R.id.TotalRecovered);
try {
Document doc = Jsoup.connect("https://www.worldometers.info/coronavirus/").userAgent("mozilla/17.0").get();
Elements temp = doc.select("div.maincounter-number");
Element totalcase = temp.get(0);
String cases = totalcase.select("div.maincounter-number span").text();
totalCases.setText(cases);
Element totaldeaths = temp.get(1);
String deaths = totaldeaths.select("div.maincounter-number span").text();
totalDeaths.setText(deaths);
Element totalrecovered = temp.get(2);
String recovered = totalrecovered.select("div.maincounter-number span").text();
totalRecovered.setText(recovered);
/* for(Element totalCase:temp)
{
String cases = totalCase.select("div.maincounter-number span").text();
System.out.println("" + cases);
*//*i++;
System.out.println(i + "" + totalCase.getElementsByTag("span"));*//*
}*/
}
catch (IOException e){
e.printStackTrace();
}
}
}
image of the app view
Image of the app view
If you could post the Error you're getting it would be easier to see what's going on, but I have two assumptions of what's wrong.
First you should check if yout Manifest is asking for INTERNET access permission. If it isn't, you should include it.
Second: Always when making requests to the internet in Android you should use either AsyncTasks or at least open a separate thread manually. That's because internet calls are asynchronous by definition, and if you block the main execution of your App to wait for a response the UI is gonna freeze or crash. So perhaps you should extract the logic of your compare() function to a separate class that inherits from AsyncTask and place it into the doInBackground() method.

Runtime Error in Async Task

I'm trying to build a simple program using Asycn Task that on clicking get button loads google home page in webview. I have no errors showing up in code however when I click the get button it crashes with the following error:
An error occured while executing doInBackground()
java.lang.RuntimeException:java.lang.Throwable:A WebView method was called on thread 'AsyncTask #1'.All WebView methods must be called on the same thread
This is my MainActivity.java
package com.example.asyncts2;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity {
Button button1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
button1.setEnabled(false);
DownloadWebPageTask task = new DownloadWebPageTask();
task.execute(new String[] {"http://www.google.com/"});
}
});
}
private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
WebView webView = (WebView) findViewById(R.id.webView1);
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl(urls[0]);
return "Done";
}
protected void onPostExecute(String result) {
Toast.makeText(MainActivity.this, "result", Toast.LENGTH_SHORT).show();
}
}
This is Log Cat errors
Can anyone point me to where I am going wrong? Many thanks!
easy way to handle that is to, whenever and wherever you want to access or modify the WebView, do it in the uithread
runOnUiThread(new Runnable() {
#Override
public void run() {
//shake the webView here!
}
});
You should not use an AsyncTask to load an URL in a webview. If you want to trigger an action when loading is complete, do like this :
webView.setWebViewClient(new WebViewClient()
{
public void onPageFinished(WebView view, String url)
{
// do something
}
});
doInBackground() method not runs in the UI thread. It runs as a separate thread which will not interact with UI. Thats why, It is not able to access your WebView which is present in UI thread. I really dont see the purpose of using an AsyncTask here. You can load your webview inside your onClick method itself. Otherwise, use onPostExecute() method to update your Webview.
Otherwise, As #eduyayo told, put the runOnUiThread() method inside your doInBackground() method and do the WebView updates inside the run() method.
You have to make those calls inside your main thread, i.e. inside your activity itself. Since AsyncTask create another thread, android restricts lots of action here. one simple way to go ahead is to mimmic call back handler . Steps to guide you ,
Create interface :
public interface IWebViewHandler {
void handleWebCall();
}
Implement this interace by your activity and override the method with your action and call this method from your asynctask.doInBackground, like
public class MainActivity extends Activity implements IWebViewHandler {
#Override
public void handleWebCall() {
//your work like action on WebViews
/* WebView webView = (WebView) findViewById(R.id.webView1);
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl(urls[0]);*/
}
private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
handleWebCall();
return "Done";
}
protected void onPostExecute(String result) {
Toast.makeText(MainActivity.this, "result", Toast.LENGTH_SHORT).show();
}
}
}
P.S : the call to handleWebCall is just for sample, modify calling method and the method implementation /signature as per your neeed.

Android bugs on device. What should I do to fix them? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
In my application I noticed these three things:
-The back button is enabled when going from one activity to another enabling the user to click on back to the original activity. The problem is I don't want the user to click on Back at a certain point in my application. I don't want to disable the back button completely in my application, only when one intent is called. How can I do that?
-I noticed something strange... when a toast notification pops up in my application all is well until I exit my application. When I exit my application, some of the toast notifications are residual and are popping outside of my application. Is there a reason for that? Did I miss something in the activity lifecycle to handle the cancellation of toasts at a certain point?
Lastly, this one is rather tough to solve. How do I lock my screen so that when the user rotates the device, that the activity doesn't not get called again and the asynctask can still resume without starting over again?
Thanks a lot for your time. Just curious why these things happen and what should I look into?
Here's my code:
//Main Activity.java
package com.example.Patient_Device;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import java.io.*;
public class MainActivity extends Activity {
//fields
private ProgressDialog progressBar;
private Context context;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.start_setup);
//Set the context
context = this;
//Initialize the start setup button and add an onClick event listener to the button
final Button start_setup_button = (Button) findViewById(R.id.start_setup_button);
start_setup_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
//Executes the AsyncTask
new RetrieveInfoTask().execute();
//Instantiates the intent to launch a new activity
Intent myIntent = new Intent(MainActivity.this, RetrieveInfoActivity.class);
MainActivity.this.startActivity(myIntent);
}
});
}
public class RetrieveInfoTask extends AsyncTask<Void, Void, Void> {
//Called on the UI thread to execute progress bar
#Override
protected void onPreExecute() {
super.onPreExecute();
progressBar = new ProgressDialog(context);
progressBar.setIndeterminate(true);
progressBar.setCancelable(false);
progressBar.setMessage(MainActivity.this.getString(R.string.retrieve_info));
progressBar.show();
}
//Methods that retrieves information from the user device. This is performed in the Background thread
private void retrieveInfo() {
try {
//Reading the drawable resource line by line
String str="";
StringBuffer buf = new StringBuffer();
InputStream is = MainActivity.this.getResources().openRawResource(R.drawable.user_info);
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
if (is!=null) {
while ((str = reader.readLine()) != null) {
buf.append(str + "\n" );
}
}
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
//doInBackground calls retrieveInfo() to perform action in Background
#Override
protected Void doInBackground(Void... params) {
retrieveInfo();
return null;
}
//When the background task is done, dismiss the progress bar
#Override
protected void onPostExecute(Void result) {
if (progressBar!=null) {
progressBar.dismiss();
}
}
}
}
//RetrieveInfoActivity.java
package com.example.Patient_Device;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.os.BatteryManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
public class RetrieveInfoActivity extends Activity {
private static String TAG = "RetrieveInfoActivity";
private Context context;
String fileLastSync = "09-18-2014 03:47 PM";
#Override
public void onCreate(Bundle savedInstanceState) {
context = this;
super.onCreate(savedInstanceState);
setContentView(R.layout.retrieve_info);
//Once the new activity is launched, the setup is complete
Toast.makeText(getApplicationContext(), "Setup Complete!",
Toast.LENGTH_LONG).show();
//Gets the 'last synced' string and sets to datetime of the last sync
Resources resources = context.getResources();
String syncString = String.format(resources.getString(R.string.last_sync), fileLastSync);
//Dynamically sets the datetime of the last sync string
TextView lastSyncTextView = ((TextView) findViewById(R.id.last_sync) );
lastSyncTextView.setText(syncString);
//calls registerReceiver to receive the broadcast for the state of battery
this.registerReceiver(this.mBatInfoReceiver,new
IntentFilter(Intent.ACTION_BATTERY_CHANGED));
}
private BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context arg0, Intent intent) {
//Battery level
int level = intent.getIntExtra("level", 0);
//Dynamically sets the value of the battery level
TextView batteryTextView = ((TextView) findViewById(R.id.battery) );
batteryTextView.setText("Battery Level: " + String.valueOf(level)+ "%");
//If the battery level drops below 25%, then announce the battery is low
//TODO: Add 25 to constants file.
if(level < 25) {
Toast.makeText(getApplicationContext(), "Low Battery!",
Toast.LENGTH_LONG).show();
}
//Plugged in Status
int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
//Battery Status
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
//If the device is charging or contains a full status, it's charging
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
//If the device isCharging and plugged in, then show that the battery is charging
if(isCharging && plugged == BatteryManager.BATTERY_PLUGGED_AC || plugged == BatteryManager.BATTERY_PLUGGED_USB) {
Toast.makeText(getApplicationContext(), "Charging.." + String.valueOf(level)+ "%",
Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getApplicationContext(), "Unplugged!",
Toast.LENGTH_LONG).show();
}
}
};
#Override
public void onDestroy() {
try {
super.onDestroy();
unregisterReceiver(this.mBatInfoReceiver);
}
catch (Exception e) {
Log.e(RetrieveInfoctivity.TAG, getClass() + " Releasing receivers-" + e.getMessage());
}
}
}
//StartSetupActivity.java
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class StartSetupActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
//FragmentsActivity.java
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class FragmentsActivity extends Fragment{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.main, container, false);
}
}
First of all whenever you want to disable back press just override onBackPressed() method and remove super. like this:
#Override
public void onBackPressed() {
//super.onBackPressed();
}
Second you'r using application context to show toast. use activity context.
Toast.makeText(this or YourActivity.this, "Setup Complete!", Toast.LENGTH_LONG).show();
Third just add this attribute into your manifest class. This will avoid recrating your activity when orientation change
android:configChanges="orientation"
I'll answer these in order:
Back Button
You can override onBackPressed in your Activity and determine if you want to consume it or let Android process it.
#Override
public void onBackPressed()
{
// Set this how you want based on your app logic
boolean disallowBackPressed = false;
if (!disallowBackPressed)
{
super.onBackPressed();
}
}
Toasts
Toasts are enqueued with the Notification Manager. If you show multiple Toasts in a row, they get queued up and shown one at a time until the queue is empty.
Locking Orientation For Activity
Use android:screenOrientation="landscape" or android:screenOrientation="portrait" on your activity element in your manifest to lock the orientation.
I think that these questions should be asked separately, because the answer in detail to every item of your question is too long, but I hope this helps:
-The back button is enabled when going from one activity to another enabling the user to click on back to the original activity. The
problem is I don't want the user to click on Back at a certain point
in my application. I don't want to disable the back button completely
in my application, only when one intent is called. How can I do that?
You can override the onBackPressed on the activities you don't want the user to go back.
#Override
public void onBackPressed() {
//Leave it blank so it doesn't do anything
}
-I noticed something strange... when a toast notification pops up in my application all is well until I exit my application. When I exit my
application, some of the toast notifications are residual and are
popping outside of my application. Is there a reason for that? Did I
miss something in the activity lifecycle to handle the cancellation of
toasts at a certain point?
I think that the reason behind that is that toast go into a que, and are showed in order, even if the app is no longer visible.
Lastly, this one is rather tough to solve. How do I lock my screen so
that when the user rotates the device, that the activity doesn't not
get called again and the asynctask can still resume without starting
over again?
For this, you can use the following code in your manifest
android:configChanges="orientation|screenSize"/>
However this is NOT recommended by google, I suggest you read the following link to get a little more information on how to handle orientation changes:
http://developer.android.com/guide/topics/resources/runtime-changes.html

The method setText string is undefined for the type view

I'm new to android and have have an assignment to create an email application. So I have 2 layouts and 2 activities, one for reading the email and one for writing the email. I'm trying to retain the information sent in the fields in the email writing activity for when the email is being read. The problem is at the **bolded line below - "The method setText string is undefined for the type view", and I need to get all the text view to contain the information send from the other activity. I can post the other files if its needed, all help appreciated. I have tried other ways to assign the variable to text view but can't seem to get it to work.
DisplayMessageActivity.java
package com.example.project;
import com.example.project.R.layout;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.view.MenuItem;
import android.widget.TextView;
public class DisplayMessageActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_message);
// Show the Up button in the action bar.
setupActionBar();
// Get the messages from the intent
Intent intent = getIntent();
String messageto2 = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
String messagefrom2 = intent.getStringExtra(MainActivity.EXTRA_MESSAGE2);
String messagecc2 = intent.getStringExtra(MainActivity.EXTRA_MESSAGE3);
String messagebcc2 = intent.getStringExtra(MainActivity.EXTRA_MESSAGE4);
String messagesubject2 = intent.getStringExtra(MainActivity.EXTRA_MESSAGE5);
String messagebody2 = intent.getStringExtra(MainActivity.EXTRA_MESSAGE6);
**TextView msgto = (TextView)findViewById(R.id.to2).setText(messageto2);**
TextView msgfrom = (TextView)findViewById(R.id.from2);
TextView msgcc = (TextView)findViewById(R.id.cc2);
TextView msgbcc = (TextView)findViewById(R.id.bcc2);
TextView msgsubject = (TextView)findViewById(R.id.subject2);
TextView msgbody = (TextView)findViewById(R.id.body2);
}
/**
* Set up the {#link android.app.ActionBar}, if the API is available.
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void setupActionBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
getActionBar().setDisplayHomeAsUpEnabled(true);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// This ID represents the Home or Up button. In the case of this
// activity, the Up button is shown. Use NavUtils to allow users
// to navigate up one level in the application structure. For
// more details, see the Navigation pattern on Android Design:
//
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
//
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
}
TIA
Try to change this:
(TextView)findViewById(R.id.to2).setText(messageto2);
to
((TextView)findViewById(R.id.to2)).setText(messageto2);
Methods are resolved according to the static type of the reference. findViewById() is declared with a return type of View and since the class View doesn't declare a method setText(), the compiler complains. Use this
TextView msgto = (TextView)findViewById(R.id.to2);
msgto.setText(messageto2);
try this..
((TextView)findViewById(R.id.to2)).setText(messageto2);
TextView msgto = (TextView)findViewById(R.id.to2).setText(messageto2);
Need to be changed to
TextView msgto = (TextView) findViewById(R.id.to2);
msgto.setText(messageto2);
That should help.

Button to vibrate makes android app force close

Im just making a simple app that will vibrate when the button is clicked, but for some reason when i click the button the app says it unexpectedly stopped and needed to force close, below is the source code to the main java file and i have used the android vibrate permission in my manifest. can someone tell me why every time I click the vibrate button it gives me the error that it unexpectedly stopped?
package com.test;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Vibrator;
import android.view.View;
import android.widget.EditText;
public class Main extends Activity {
public final static String EXTRA_MESSAGE = "com.test.MESSAGE";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
/* Called when the user clicks the button */
public void sendMessage(View view) {
// do something in response to button
Intent intent = new Intent(this, DisplayMessageActivity.class);
EditText editText = (EditText) findViewById(R.id.edit_message);
String message = editText.getText().toString();
intent.putExtra(EXTRA_MESSAGE, message);
startActivity(intent);
}
public void vibrateMe() {
Vibrator vibrate = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
vibrate.vibrate(500);
}
public void stopVibrating(Vibrator vibrate) {
vibrate.cancel();
}
}
You have to change your vibrateMe() to vibrateMe(View v) if you use android:onClick="vibrateMe"
For instance, if you specify android:onClick="sayHello", you must
declare a public void sayHello(View v) method of your context
(typically, your Activity).
Check the developer page
public void stopVibrating(Vibrator vibrate) {
vibrate.cancel();
}
remove this and then check.

Categories