An error occured while executing doInBackground? - java

Here is my code
package com.example.rollsystems;
import java.util.ArrayList;
import org.dto.Student;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.TextView;
import android.app.Activity;
import android.content.Context;
import com.example.listview.*;
import com.example.Utils.AllBO;
import com.example.rollsystems.R;
public class RollCallActivity extends Activity {
ArrayList<Student> array;
ListStudentAdapter arrayAdapter;
ListView list;
TextView txtClassAt;
TextView txtSubjectAt;
TextView txtInstructorAt;
TextView txtTimeAt;
TextView txtDateAt;
Context context;
public class RollCallTask extends AsyncTask<Void, Void, Void> {
public RollCallActivity activity;
public RollCallTask(RollCallActivity a)
{
activity = a;
}
#Override
protected Void doInBackground(Void... params) {
//SharedPreferences sharedPref = getApplicationContext().getSharedPreferences("rs", Context.MODE_PRIVATE);
//String RollCallID = sharedPref.getString("RollCallID", "14");
String RollCallID = "14";
list = (ListView)findViewById(R.id.listAtStudent);
ArrayList<Student> rollCalls = new AllBO().getRollCallInfo(RollCallID);
array = rollCalls;
return null;
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
arrayAdapter = new ListStudentAdapter(activity, R.layout.list_atstudent, array);
list.setAdapter(arrayAdapter);
txtClassAt = (TextView) findViewById(R.id.txtClassAt);
}
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab_rollcall);
new RollCallTask(this).execute();
txtClassAt = (TextView) findViewById(R.id.txtClassAt);
}
}
And then, when i run:
E/AndroidRuntime(883): FATAL EXCEPTION: AsyncTask #1
E/AndroidRuntime(883): java.lang.RuntimeException: An error occured while executing
doInBackground()
E/AndroidRuntime(883): at android.os.AsyncTask$3.done(AsyncTask.java:278)
every help is precious

The async task is accessing the UI. Don't do findViewById in it, use onCreate from the Activity/Fragment.
Here are also several convention issues:
String RollCallID = "14";
list = (ListView)findViewById(R.id.listAtStudent);
ArrayList<Student> rollCalls = new AllBO().getRollCallInfo(RollCallID);
array = rollCalls;
variables should never start with an uppercase rollCallID
xml id's should not be camel cased R.id.list_as_student
array is not used outside the adapter, why use a variable outside of it?

Use the Handler object from your MainActivity and post a runnable. To use it from the backgrund you need to make the object a static that you can call outside of your MainActivity or you can create a static instance of the Activity to access it.
Inside the Activity
private static Handler handler;
handler = new Handler();
handler().post(new Runnable() {
public void run() {
//ui stuff here :)
}
});
public static Handler getHandler() {
return handler;
}
Outside the Activity
MainActivity.getHandler().post(new Runnable() {
public void run() {
//ui stuff here :)
}
});

You're trying to access the UI from a background thread. You'll need to do that outside of doInBackground.
You also must call AsyncTask from the UI Thread. Failing to do so is the cause of your runtime error.
public class RollCallTask extends AsyncTask<Void, Void, Void> {
public RollCallActivity activity;
public RollCallTask(RollCallActivity a)
{
activity = a;
}
#Override
protected Void doInBackground(Void... params) {
//SharedPreferences sharedPref = getApplicationContext().getSharedPreferences("rs", Context.MODE_PRIVATE);
//String RollCallID = sharedPref.getString("RollCallID", "14");
String RollCallID = "14";
ArrayList<Student> rollCalls = new AllBO().getRollCallInfo(RollCallID);
array = rollCalls;
return null;
}
}
And then your onCreate would be
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab_rollcall);
list = (ListView)findViewById(R.id.listAtStudent);
txtClassAt = (TextView) findViewById(R.id.txtClassAt);
new RollCallTask(this).execute();
}

Related

How to add text to TextView from Loader

Now I'm studying Threads and my task is to make a counter, which will add number from 0 to 9 to TextView with the help of Loader. Of course, I know that it isn't the best variant to use Loader for such tasks, but I'd like to understand how does it work.
So, I have the following code:
package asus.example.com.exercise4;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class LoaderActivity extends AppCompatActivity {
private TextView counter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_threads);
Button startButton = findViewById(R.id.start_button);
Button cancelButton = findViewById(R.id.cancel_button);
startButton.setOnClickListener(listener);
cancelButton.setOnClickListener(listener);
counter = findViewById(R.id.counter);
}
private View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.start_button:
getSupportLoaderManager().initLoader(0, null, new LoaderClass());
break;
case R.id.cancel_button:
break;
}
}
};
#SuppressLint("StaticFieldLeak")
class AsyncTaskLoaderClass extends AsyncTaskLoader<Void>{
AsyncTaskLoaderClass(#NonNull Context context) {
super(context);
}
#Nullable
#Override
public Void loadInBackground() {
for (int i = 0; i<10;i++){
counter.setText(i);
SystemClock.sleep(500);
}
return null;
}
}
private class LoaderClass implements LoaderManager.LoaderCallbacks<Void>{
#NonNull
#Override
public Loader<Void> onCreateLoader(int i, #Nullable Bundle bundle) {
return new LoaderActivity.AsyncTaskLoaderClass(LoaderActivity.this);
}
#SuppressLint("SetTextI18n")
#Override
public void onLoadFinished(#NonNull Loader<Void> loader, Void aVoid) {
counter.setText("Done!");
}
#Override
public void onLoaderReset(#NonNull Loader<Void> loader) {
}
}
}
When I run the project I have a runtime error:
java.lang.IllegalArgumentException: Object returned from onCreateLoader must not be a non-static inner member class: AsyncTaskLoaderClass{eed39bf id=0}
Yes, I understand, that it means that AsyncTaskLoaderClass should be in another file or static, but in such case I won't have an opportunity to add text to textview. So, how can I solve this problem?
UPD
I changed the code in clicking start button in such way:
case R.id.start_button:
Loader loader = getSupportLoaderManager().initLoader(0, null, LoaderActivity.this);
loader.forceLoad();
Log.i(TAG, "Button start clicked");
break;
And now each time in the loop I have the following error:
E/e.com.exercise: Invalid ID 0x00000009.
E/EventBus: Could not dispatch event: class asus.example.com.exercise4.LoaderActivity$MyAsyncTaskLoader$ProgressEvent to subscribing class class asus.example.com.exercise4.LoaderActivity
android.content.res.Resources$NotFoundException: String resource ID #0x9
UPD 2
Finally fixed the problem in the following way:
Was
counter.setText(i);
Now
counter.setText(""+i);
Probably I don't understrand why it works, but it works
Make the Activity implement LoaderCallbacks. Also a Loader retrieves one particular value in its onLoadFinished callback, and it should return the retrieved (loaded) item as a result.
To change what value is being loaded by a Loader, you're supposed to restart the loader with a new argument bundle, and pass in the parameters so that it knows what it is doing.
Then again, you are trying to create something like "publishProgress" in AsyncTask; Loaders cannot do that out of the box, and need some variant of "sending an event" (handler threads if you are adventurous, but most likely an event bus, see implementation 'org.greenrobot:eventbus:3.1.1').
TL;DR: use EventBus for this.
public class LoaderActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Void> {
private TextView counter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_threads);
Button startButton = findViewById(R.id.start_button);
Button cancelButton = findViewById(R.id.cancel_button);
counter = findViewById(R.id.counter);
startButton.setOnClickListener((view) -> {
getSupportLoaderManager().initLoader(0, null, LoaderActivity.this);
});
cancelButton.setOnClickListener((view) -> {
// do nothing, apparently
});
EventBus.getDefault().register(this);
}
#Override
protected void onDestroy() {
EventBus.getDefault().unregister(this);
super.onDestroy();
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void onLoaderProgressEvent(MyAsyncTaskLoader.ProgressEvent event) {
counter.setText("" + event.getNumber());
}
#NonNull
#Override
public Loader<Void> onCreateLoader(int i, #Nullable Bundle bundle) {
return new MyAsyncTaskLoader(LoaderActivity.this);
}
#SuppressLint("SetTextI18n")
#Override
public void onLoadFinished(#NonNull Loader<Void> loader, Void aVoid) {
counter.setText("Done!");
}
#Override
public void onLoaderReset(#NonNull Loader<Void> loader) {
}
public static class MyAsyncTaskLoader extends AsyncTaskLoader<Void> {
public static class ProgressEvent {
private final int number;
public ProgressEvent(int number) {
this.number = number;
}
public int getNumber() { return number; }
}
public MyAsyncTaskLoader(#NonNull Context context) {
super(context);
}
#Nullable
#Override
public Void loadInBackground() {
for (int i = 0; i<10;i++){
EventBus.getDefault().post(new ProgressEvent(i));
SystemClock.sleep(500);
}
return null;
}
}
}
Your are using inner AsyncTaskLoaderClass in Activity class. Inner class holds the reference of Outer class. That means your AsyncTaskLoaderClass may hold Activity reference in some cases. Make your inner class static.
You have 2 solutions. Make AsyncTaskLoaderClass a separate class file or make AsyncTaskLoaderClass a static class.
make textview public static like this public static TextView counter;

Android Studio error: "Method getText must be called from the UI Thread, currently inferred thread is worker

I got a problem about gettext(), Android studio says that 'method getText must be called from the UI Thread,currently inferred thread is worker'. Can someone help me with this or can someone give an idea how to fix this?
Thanks!
package com.ibm.watsonvoicetts;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.ibm.watson.developer_cloud.android.library.audio.StreamPlayer;
import com.ibm.watson.developer_cloud.text_to_speech.v1.TextToSpeech;
import com.ibm.watson.developer_cloud.text_to_speech.v1.model.Voice;
public class MainActivity extends AppCompatActivity {
TextView textView;
EditText editText;
Button button;
StreamPlayer streamPlayer;
private TextToSpeech initTextToSpeechService(){
TextToSpeech service = new TextToSpeech();
String username = "";
String password = "";
service.setUsernameAndPassword(username, password);
return service;
}
private class WatsonTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... textToSpeak) {
runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText("running the Watson thread");
}
});
TextToSpeech textToSpeech = initTextToSpeechService();
streamPlayer = new StreamPlayer();
streamPlayer.playStream(textToSpeech.synthesize(
String.valueOf(editText.getText()),【**here is the problem**】
Voice.EN_MICHAEL).execute());
return "text to speech done";
}
#Override
protected void onPostExecute(String result) {
textView.setText("TTS status: " + result);
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.editText);
button = (Button) findViewById(R.id.button);
textView = (TextView) findViewById(R.id.textView);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
System.out.println("the text to speech: " + editText.getText());
textView.setText("TTS: " + editText.getText());
WatsonTask task = new WatsonTask();
task.execute(new String[]{});
}
});
}
}
You shouldn't call getText from an AsyncTask like you're doing. The solution is to pass the value into the task's constructor.
Change
WatsonTask task = new WatsonTask(editText.getText());
and
private class WatsonTask extends AsyncTask<String, Void, String> {
private final String text;
public WatsonTask(String text) {
super();
this.text = text;
}
and
streamPlayer.playStream(textToSpeech.synthesize(
String.valueOf(text),
Voice.EN_MICHAEL).execute());
doInBackground() method runs on different thread not in UI thread.
streamPlayer.playStream(textToSpeech.synthesize(
String.valueOf(editText.getText()),【**here is the problem**】
Voice.EN_MICHAEL).execute());
You are calling getText() method of edittext in this doInBackground() method. That's why it's giving error. Any work of view related things, we have to do it in UI thread.
One thing you can do it, you can place this code within runOnUiThread.

TextView does not show log

Okay I am new with android and i have been following a course but there are somethings that i don't understand.
This is LifeCycleT activity.
package com.example.killtheviolence.myapplication;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
public class LifeCycleT extends Activity {
StringBuilder builde = new StringBuilder();
TextView textview;
private void log(String text) {
Log.d("LifeCycleT", text);
builde.append( builde.toString() );
builde.append("\n");
textview.setText(builde.toString());
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView textview = new TextView(this);
textview.setText(builde.toString());
setContentView(textview);
}
protected void onResume() {
super.onResume();
log("resume");
}
protected void onPause() {
super.onPause();
log("paused");
if(isFinishing()) {
log("death");
}
}
}
Where this came from? From a ListView.
package com.example.killtheviolence.myapplication;
import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
public class MainActivity extends ListActivity {
String prueva[] = {"LifeCycleT","item2","item3","item4",
"item5 ", "item6 "};
public void onCreate(Bundle savedInstanceSate){
super.onCreate(savedInstanceSate);
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, prueva));
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
String gate = prueva[position];
try {
Class<?> inst;
inst = Class.forName("com.example.killtheviolence.myapplication." + gate);
Intent intent = new Intent(this, inst);
startActivity(intent);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
That's the main activity.
What I want to do show in the TextView the Log.d in the screen but I get an error:
Unable to resume activity
{com.example.killtheviolence.myapplication/com.example.killtheviolence.myapplication.LifeCycleT}:
java.lang.NullPointerException
So I looked for a reason (meaning for a NullPointerException and it was that
I used TextView before initializing on the line textview.setText(builde.toString());
What I did was create an instance of TextView in log function.
private void log(String text) {
Log.d("LifeCycleT", text);
builde.append(builde.toString());
builde.append("\n");
TextView textview = new TextView(this);
textview.setText(builde.toString());
}
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
TextView textview = new TextView(this);
textview.setText(builde.toString());
setContentView(textview);
}
Why have I to create two instances of TextView? And why have I to setText twice? Why doesn't it show anything in the TextView? (only shows when i wrote a "string" in the arguments of setText.)
fix your onCreate to set the field parameter not a local parameter:
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
textview = new TextView(this); // << This used to be a local var, thats why NPE
textview.setText(builde.toString());
setContentView(textview);
}
Then remove the 2nd creation of the TextView from log
private void log(String text) {
Log.d("LifeCycleT", text);
builde.append("\n");
builde.append(text);
textview.setText(builde.toString());
}
Also notice that I changed your StringBuilder to append the text that you pass as a parameter into your log method

Android Calling Method in Activity Class

I have java class called Second.java which has a method called toast_method().
My question is, How can i call the toast_method() from the Second.java and then display the toast message in the app?
I tried the following code but it's not working
Second.java
package com.example.callmethod;
import android.content.Context;
import android.widget.Toast;
public class Second {
Context context;
public Second(Context context) {
this.context = context;
}
public void toast_method() {
Toast.makeText(context, "Hello", Toast.LENGTH_SHORT).show();
}
}
MainActivity.java
package com.example.callmethod;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
private Second myotherclass;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Calling the method from Second Class
myotherclass.toast_method();
}
}
Thanks
You are nearly there! Only missing the vital instantiation of the second class:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Calling the method from Second Class
myotherclass = new Second(this); // <----- this
myotherclass.toast_method();
}
do it in onCreate Like this
Second second =new Second(this);
second.toast_method();
Easy one ^^
you have to extends Activity to use context in the activity
public class operation extends Activity {
// normal toast
//you can change length
public static void toast(String toastText, Context contex) {
Toast.makeText(contex, toastText, Toast.LENGTH_LONG).show();
}
// Empty Toast for Testing
public static void emptyToast(Context contex) {
Toast.makeText(contex, R.string.EmptyText, Toast.LENGTH_LONG).show();
}
}
now ... in your activity only call function
operation.toast("Your Text",currentClass.this);
Example :
public class currentClass extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mylayout);
operation.toast("Hello",currentClass.this);
}
}

Cannot save entity from android app to Google App Engine backend

I am following the examples given in the Google tutorial to create a Google App Engine backend for my android app.
In the tutorial, the MainActivity is as follows:
import java.io.IOException;
import java.util.Date;
import android.os.AsyncTask;
import android.content.Context;
import com.cloudnotes.noteendpoint.Noteendpoint;
import com.cloudnotes.noteendpoint.model.Note;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.json.jackson.JacksonFactory;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new EndpointsTask().execute(getApplicationContext());
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public class EndpointsTask extends AsyncTask<Context, Integer, Long> {
protected Long doInBackground(Context... contexts) {
Noteendpoint.Builder endpointBuilder = new Noteendpoint.Builder(
AndroidHttp.newCompatibleTransport(),
new JacksonFactory(),
new HttpRequestInitializer() {
public void initialize(HttpRequest httpRequest) { }
});
Noteendpoint endpoint = CloudEndpointUtils.updateBuilder(
endpointBuilder).build();
try {
Note note = new Note().setDescription("Note Description");
String noteID = new Date().toString();
note.setId(noteID);
note.setEmailAddress("E-Mail Address");
Note result = endpoint.insertNote(note).execute();
} catch (IOException e) {
e.printStackTrace();
}
return (long) 0;
}
}
}
This worsk fine and the entities are created everytime i run the app.So i modified it by adding textfields to get the values of description and email from the user and got this as the new MainActivity
public class MainActivity extends Activity implements View.OnClickListener{
EditText descriptionTF;
EditText emailTF;
Button submitBtn;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
submitBtn = (Button) findViewById(R.id.submitButton);
descriptionTF = (EditText) findViewById(R.id.descriptionTextField);
emailTF = (EditText) findViewById(R.id.emailTextField);
}
public class EndpointsTask extends AsyncTask<Context, Integer, Long> {
protected Long doInBackground(Context... contexts) {
Noteendpoint.Builder endpointBuilder = new Noteendpoint.Builder(
AndroidHttp.newCompatibleTransport(),
new JacksonFactory(),
new HttpRequestInitializer() {
public void initialize(HttpRequest httpRequest) { }
});
Noteendpoint endpoint = CloudEndpointUtils.updateBuilder(
endpointBuilder).build();
String descrptn = descriptionTF.getText().toString();
String email = emailTF.getText().toString();
String noteID = new Date().toString();
try {
Note note = new Note();
note.setDescription(descrptn);
note.setId(noteID);
note.setEmailAddress(email);
Note result = endpoint.insertNote(note).execute();
} catch (IOException e) {
e.printStackTrace();
}
return (long) 0;
}
}
#Override
public void onClick(View v) {
if (v.getId()== R.id.submitButton) {
new EndpointsTask().execute(getApplicationContext());
}
}
}
Now nothing happens when i click the submit button.
I am guessing the problem is from me calling new EndpointsTask().execute(getApplicationContext()); from the onClick() method instead of the onCreate() method as it was done in the tutorial.Does anyone know a way around this?
Finally solved this problem by moving the onClick() method to the onCreate() method like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
submitBtn = (Button) findViewById(R.id.submitButton);
descriptionTF = (EditText) findViewById(R.id.descriptionTextField);
emailTF = (EditText) findViewById(R.id.emailTextField);
submitBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (v.getId()== R.id.submitButton) {
new EndpointsTask().execute(getApplicationContext());
}
}
});
}

Categories

Resources