I am using OkHttpClient to get the Staff List (in JSON form) as response using AsyncTask Function. After getting the response in AsyncTask funtion, while inserting staff list in database, I want to show the count on the screen. but it gives following error. I tried many solutions, but couldn't resolve.
Following is the synchronizeStaffList Activity that calls SenkronizeEt Funtion using handler.
public class synchronizeStaffList extends AppCompatActivity {
DatabaseHelper gksDatabase;
TextView txtrecordValue;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_synchronize_staff_list);
gksDatabase = new DatabaseHelper(this);
txtrecordValue = (TextView) findViewById(R.id.txtrecordValue);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Do something after 100ms
SenkronizeEt();
}
}, 500);
final Handler handler2 = new Handler();
handler2.postDelayed(new Runnable() {
#Override
public void run() {
//Do something after 100ms
AlertDialog.Builder builder;
builder = new AlertDialog.Builder(synchronizeStaffList.this);
builder.setCancelable(false);
if (progressStaffListInfo == 0) {
builder.setMessage("Sunucu ile iletişim yok");
} else if (progressStaffListInfo == 1) {
builder.setMessage("Sicil/Personel listesi güncellendi");
}
builder.setPositiveButton("Tamam", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// if user pressed "MINIMIZE", cancel this dialog & minimize the application
// while attendance process will keep working in the back
// finish();
startActivity(new Intent(synchronizeStaffList.this, synchronize.class));
finish();
}
});
AlertDialog alert = builder.create();
alert.show();
}
}, 5000);
}
I uses second handler to show an alertbox.
Following the SenkronizeEt Function that call OkHttpHandler AsyncTask function to get the okHttpResponse/result
public int progressStaffListInfo = 0; // 0: List no updated, 1: List updated,
private void SenkronizeEt() {
progressStaffListInfo = 0;
// Updating Staff List in device by calling webservices
HashMap<String, String> Parametre = gksDatabase.GetParameter();
final String urlStaffList = "http://127.0.0.1:8080/JAXRSJsonCRUDExample/rest/employees/" + Parametre.get("DeviceNo");
OkHttpHandler handler = new OkHttpHandler();
String jsonEmployeesList = null;
try {
jsonEmployeesList = handler.execute(urlStaffList).get();
} catch (Exception e) {
//tv.setText("sorry, something went wrong !");
}
if (progressStaffListInfo == 0) {
Toast.makeText(synchronizeStaffList.this, "List Not Updated", Toast.LENGTH_SHORT).show();
} else if (progressStaffListInfo == 1) {
Toast.makeText(synchronizeStaffList.this, "List updated in database", Toast.LENGTH_SHORT).show();
}
}
Here is the OkHttpHandler AsyncTask function that call the URL to get the response and then update it in database.
public class OkHttpHandler extends AsyncTask<String, Integer, String> {
OkHttpClient client = new OkHttpClient();
#Override
protected String doInBackground(String... params) {
Request.Builder builder = new Request.Builder();
builder.url(params[0]);
Request request = builder.build();
try {
Response response = client.newCall(request).execute();
// return response.body().string();
String jsonData = response.body().string();
//JSONObject Jobject = new JSONObject(jsonData);
//JSONArray Jarray = Jobject.getJSONArray("employees");
JSONArray Jarray = new JSONArray(jsonData);
//get the length of the json array
int limit = Jarray.length();
if (limit != 0) {
gksDatabase.PersonsDelete();
progressStaffListInfo = 1; // Staff List updated
}
for (int i = 0; i < limit; i++) {
JSONObject object = Jarray.getJSONObject(i);
//store the data into database
// SId:StaffID SNo:StaffNumber SN:StaffName CNo:CardNumber
gksDatabase.PersonsSave(Integer.parseInt(object.getString("sid")), object.getString("sno"), object.getString("sn"),
object.getString("cno")
);
publishProgress((int) (((i+1) / (float) limit) * 100));
}
return jsonData;
} catch (JSONException e) {
progressStaffListInfo = 0;
} catch (Exception e) {
e.printStackTrace();
progressStaffListInfo = 0;
}
return null;
}
#Override
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
}
private void setProgressPercent(int progValue){
txtrecordValue.setText(progValue);
}
In above AsyncTask function, it gives error when it try to display the count of entries inserted in database.
Actually, not only this. if I set any thing (Like progressbar or count) on different thread, even then it stops till the asyncTask finishes its work. As an example AlertDialog handler also starts when AsyncTask function finishes all its work.
Following are the logs:
E/AndroidRuntime: FATAL EXCEPTION: main android.content.res.Resources$NotFoundException: String resource ID #0x0
at android.content.res.Resources.getText(Resources.java:249)
at android.support.v7.widget.ResourcesWrapper.getText(ResourcesWrapper.java:52)
at android.widget.TextView.setText(TextView.java:3796)
at com.emiturk.gsk.synchronizeStaffList.setProgressPercent(synchronizeStaffList.java:172)
at com.emiturk.gsk.synchronizeStaffList.access$100(synchronizeStaffList.java:25)
at com.emiturk.gsk.synchronizeStaffList$OkHttpHandler.onProgressUpdate(synchronizeStaffList.java:167)
at com.emiturk.gsk.synchronizeStaffList$OkHttpHandler.onProgressUpdate(synchronizeStaffList.java:116)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:647)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4810)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
at dalvik.system.NativeStart.main(Native Method
Kindly help me out.
You cannot set int value on textView so it should be a String object so do it like
private void setProgressPercent(int progValue){
txtrecordValue.setText(""+progValue);
}
""+ will implicitly convert your progValue to String as if first parameter is a string (which it is empty string "") along with + then other will be promoted to string
Related
I use Looper.prepare and Looper.loop in Runnable's run function. But the problem is that the thread not loop at all, the Runnable just run one time. In Activity1, I use three Runnable threads, all looping. Two threads get Data and pictures from net constantly through "while" loop(needn't update UI), one thread select data and pic from local sqlite constantly through "Looper". The data is:
protected void onCreate(Bundle savedInstanceState) {
......
new Thread(getMessageTask).start();
getMessageHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
i++;
System.out.println("niuanmata" + i); //one appear the first one
try {
ArrayList<Map<String, String>> listMessages = (ArrayList<Map<String, String>>)msg.obj;
boolean listchange = true;
if (oldMessages.size() != 0) {
if (listMessages.size() == oldMessages.size()) {
for (int i = 0; i < listMessages.size(); i++) {
Map<String, String> oldmessage = (Map<String, String>) oldMessages.get(i);
Map<String, String> newmessage = (Map<String, String>) listMessages.get(i);
if ((oldmessage.get("mID") != newmessage.get("mID")) || (oldmessage.get("mainContent") != newmessage.get("mainContent")) || (oldmessage.get("deadLine") != newmessage.get("deadLine"))) {
break;
}
if (i == (listMessages.size() - 1)) {
listchange = false;
}
}
}
}
if (listchange) {
SimpleAdapter adapter = new SimpleAdapter(MainActivity.this, listMessages, R.layout.layout_invites,
new String[]{"mID", "creater", "mainContent", "deadLine", "mtype", "createrLogo"},
new int[]{R.id.tv_list_type, R.id.tv_list_name, R.id.tv_list_inviteword, R.id.tv_list_invitedate, R.id.tv_list_inviteid, R.id.iv_list_logo});
lvMessage.setAdapter(adapter);
oldMessages = listMessages;
}
} catch (Exception e) {
Toast.makeText(MainActivity.this, "wrong: " + e.toString(), Toast.LENGTH_SHORT).show();
return;
}
}
};
......
lvMessage.setOnItemClickListener(new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) { //when creater click, update the message; when others click, reset the alarm
Toast.makeText(MainActivity.this, "ok" , Toast.LENGTH_SHORT).show();
}
});
}
.........
Runnable synchroDataTask = new Runnable() {
#Override
public synchronized void run() {
//data syschno
while (IOHelper.loopjudge()) {
{
AccountsDB adb = new AccountsDB(MainActivity.this);
String thelastupdate = adb.getLastUpdate(account.getChatNO());
Calendar calendar = IOHelper.StringToCalendar(thelastupdate);
calendar.add(Calendar.MINUTE, -30);
String accountData = synchroDataWebservice(account.getChatNO(), IOHelper.CalendarToString(calendar)); //get the datas of the account synchroly
AccountBLL.saveDBofWebString(accountData, MainActivity.this, account); //use static method to save the DB string as SQLite data
}
}
.........
#Override
public synchronized void run() {
while (IOHelper.loopjudge()) {
......
}
.......
Runnable getMessageTask = new Runnable() {
#Override
public synchronized void run() {
Looper.prepare();
//while (IOHelper.loopjudge() && (!stopThread)) {
MessageDB messagedb = new MessageDB(MainActivity.this);
List<MessageMain> messages = messagedb.getMessageByChatNO(account.getChatNO());
ArrayList<Map<String, String>> listMessages = setMessaageListToMap(messages);
Message msg = Message.obtain();
msg.obj = listMessages;
getMessageHandler.sendMessageDelayed(msg, 1000);
//}
Looper.loop();
}
};
......
In my limited experience with android, I use while to do the Loop in getMessageTask , because the data and UI's listview need to be updated constantly. But the listview can not be clicked. Then change to Looper, but the the UI's listview can't be updated constantly....
The answer is that I misunderstand the meaning of Looper, think the Looper.prepare() and Looper.loop() as the while() loop, then make the mistake.
Looper.prepare() and Looper.loop() just means that this thread can be looped, but I must write while loop or for loop by myself.
I have an activity that calls JSON data from a foreign database.
Below is my ideal case for my app:
The JSON data is parsed and inserted into an SQLite database on Android
Next activity is started and the newly inserted data is read from the SQLite database
What actually happens:
The JSON data is parsed and inserted into an SQLite database on Android
The next activity is started while data is still being inserted and returns zero when reading from the desired databse for my ListArray in that activity.
How do I force Android to wait until database insertion is completed before starting the next activity?
EDIT
My doInBackground looks as follows:
#Override
protected String doInBackground(String... params) {
StringRequest strReq = new StringRequest(Request.Method.GET,
str, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jObj = new JSONObject(response);
boolean error = jObj.getBoolean("error");
// Check for error node in json
if (!error) {
JSONArray jObjInside = jObj.getJSONArray("service_prov_services");
for (int i = 0; i < jObjInside.length(); i++) {
// Now store the user in SQLite
try {
// JSONObject user = jObj.getJSONObject("user");
String service_prov_type = jObj.getString("service_prov_type");
String service_prov_name = jObj.getString("service_prov_name");
String addr_street = jObj.getString("addr_street");
String addr_num = jObj.getString("addr_number");
String addr_plz = jObj.getString("addr_plz");
String addr_city = jObj.getString("addr_city");
JSONObject elem = jObjInside.getJSONObject(i);
if(elem != null){
String service_id = elem.getString("service_id");
String service_type = elem.getString("service_type");
String service_measure = elem.getString("service_measure");
// Inserting row in userServiceProvServices table
db.addUserServiceProvServices(service_id, service_prov_type,
service_prov_name, addr_street, addr_num, addr_plz, addr_city, service_type, service_measure);
Log.d("post_url for service", addr_plz );
}
} catch (JSONException e) {
// JSON error
e.printStackTrace();
Toast.makeText(getActivity().getApplicationContext(), "Json error: " +
e.getMessage(), Toast.LENGTH_LONG).show();
}
}
} else {
// Error in login. Get the error message
String errorMsg = jObj.getString("error_msg");
Toast.makeText(getActivity().getApplicationContext(),
errorMsg, Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
// JSON error
e.printStackTrace();
Toast.makeText(getActivity().getApplicationContext(), "Json error: " +
e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Login Error: " + error.getMessage());
Toast.makeText(getActivity().getApplicationContext(),
error.getMessage(), Toast.LENGTH_LONG).show();
}
});
Log.d("test string to appcntr",strReq.toString());
// Adding request to request queue
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
return params[0];
}
onPostExecute looks as follows:
#Override
protected void onPostExecute(String Result) {
//super.onPostExecute(Result);
pdLoading.dismiss();
//this method will be running on UI thread
Log.d(TAG, "Stamp: " + Result);
Bundle args = new Bundle();
args.putString("stampID", Result);
ProviderServiceListFragment frag = new ProviderServiceListFragment();
frag.setArguments(args);
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame,
frag)
.commit();
}
With the way I am doing it now, my next Fragment is already called, although the data has not finished being entered into the database. This means the ListArray in the follwoing Fragment is empty because of the missing database data.
I worked on this for a month and finally figured it out for myself (stupid nube I am..) So here is a piece of code inserting a record to sqlite.
On the chosen event ("onClick actionbutton1") a new AsyncTask is created with doInBackground, onPreExecute and onPostExecute.
onPreExecute will setMessage() and show() the progressDialog which will start spinning
onPostExecute will handle the new/next Activity
READ BELOW FOR doInBackground!!
actionButton1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final ProgressDialog progressDialog = new ProgressDialog(AddUpdateEvf.this);
new AsyncTask<Void, Void, Boolean>() {
protected Boolean doInBackground(Void... params) {
doOneThing();
return null;
}
#Override
protected void onPreExecute() {
progressDialog.setMessage("Processing...");
progressDialog.show();
}
protected void onPostExecute(Boolean result) {
evaluationFormOps.close();
progressDialog.dismiss();
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(AddUpdateEvf.this);
alertDialogBuilder.setMessage("Added to Database...")
.setCancelable(false)
.setPositiveButton("Continue", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
i = new Intent(AddUpdateEvf.this, ViewProduct.class);
i.putExtra(EXTRA_ADD_UPDATE, "View");
i.putExtra(EXTRA_PRODUCT_ID, hiddenTextId.getText().toString());
i.putExtra(EXTRA_PRODUCT_NO, productNo_tv.toString());
startActivity(i);
dialog.dismiss();
finish();
}
});
AlertDialog alert = alertDialogBuilder.create();
alert.show();
}
private void doOneThing() {
makeDbRequest();
do {
evfId = newEvf.getEvfId();
}
while (evfId<1);
}
}.execute();
}
});
Note this snippet in the above code called in doInBackground():
private void doOneThing() {
makeDbRequest();
do {
evfId = newEvf.getEvfId();
}
while (evfId<1);
}
Note: The makeDbRequest() handles the insert to sqlite by setting the values and then passing it to another class which handles the cursor and puts the values etc.
Heres a small snippet of relevant code in that class (which you should already have mastered...):
public Evf addEvf(Evf evf, String dBsuccess){
ContentValues values = new ContentValues();
values.put(TableHelper.PRODUCT_IDE,evf.getPRODUCTId());
values.put(TableHelper.CSCORE,evf.getcScore());
values.put(TableHelper.FSCORE,evf.getfScore());
values.put(TableHelper.TSCORE,evf.gettScore());
values.put(TableHelper.WEIGHT,evf.getWeight());
values.put(TableHelper.TEMP,evf.getTemp());
values.put(TableHelper.STATUS,evf.getStatus());
values.put(TableHelper.TIMESTAMP, String.valueOf(evf.getTimeStamp()));
values.put(TableHelper.LOADED, dBsuccess);
long insertid = database.insert(TableHelper.TABLE_EVFS,null,values);
evf.setEvfId((int) insertid);
return evf;
}
So above you can see the Id of, in my case evaluationform(Evf), being set to the insert id. This happens after the insert and you can set any value in your object class (the one with getters and setters...Evf())
Finally, use the do...while statement above to "listen" for the value being set in the object class
This can obviously only happen if the insert was finished and the onPosteExecute takes care of the rest
Hope it helps, crit is welcome, PEACHES!!
Use AsyncTask to process the Database insertion process & then use the onPostExecute method to move away from the current activity.
private class ProcessDatabase extends AsyncTask<String, String, String> {
String sampleData;
#Override
protected String doInBackground(String... params) {
//Call your Database Insert method here.
//In this example, I am inserting sampleData to the DB
return null;
}
#Override
protected void onPostExecute(String result) {
//This gets triggered when the process is complete
}
}
You can start the AsyncTask by adding the following code in your onCreate or where ever you want to start the DB Insertion process:
//in this case I am just passing a string, You can create your own
//custom class & send that as well
ProcessDatabase.execute(myData);
Refer this link for more information. Good luck!
The StringRequest is an Asynchronous request, so upon the executing the those lines onPostExecute will called immediately, so there is no guarantee that the sql update will complete before the next activity is launched.
Call the nextActivity at the end of the onResponse callback method of the StringRequest which way you can guarantee to insert the data to db first and then call the nextActivity.
private void makeJsonRequest(String str) {
StringRequest strReq = new StringRequest(Request.Method.GET,
str, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jObj = new JSONObject(response);
boolean error = jObj.getBoolean("error");
// Check for error node in json
if (!error) {
JSONArray jObjInside = jObj.getJSONArray("service_prov_services");
for (int i = 0; i < jObjInside.length(); i++) {
// Now store the user in SQLite
try {
// JSONObject user = jObj.getJSONObject("user");
String service_prov_type = jObj.getString("service_prov_type");
String service_prov_name = jObj.getString("service_prov_name");
String addr_street = jObj.getString("addr_street");
String addr_num = jObj.getString("addr_number");
String addr_plz = jObj.getString("addr_plz");
String addr_city = jObj.getString("addr_city");
JSONObject elem = jObjInside.getJSONObject(i);
if (elem != null) {
String service_id = elem.getString("service_id");
String service_type = elem.getString("service_type");
String service_measure = elem.getString("service_measure");
// Inserting row in userServiceProvServices table
db.addUserServiceProvServices(service_id, service_prov_type,
service_prov_name, addr_street, addr_num, addr_plz, addr_city, service_type, service_measure);
Log.d("post_url for service", addr_plz);
}
} catch (JSONException e) {
// JSON error
e.printStackTrace();
Toast.makeText(getActivity().getApplicationContext(), "Json error: " +
e.getMessage(), Toast.LENGTH_LONG).show();
}
}
goNextActivity();
} else {
// Error in login. Get the error message
String errorMsg = jObj.getString("error_msg");
Toast.makeText(getActivity().getApplicationContext(),
errorMsg, Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
// JSON error
e.printStackTrace();
Toast.makeText(getActivity().getApplicationContext(), "Json error: " +
e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Login Error: " + error.getMessage());
Toast.makeText(getActivity().getApplicationContext(),
error.getMessage(), Toast.LENGTH_LONG).show();
}
});
Log.d("test string to appcntr", strReq.toString());
// Adding request to request queue
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
}
private void goNextActivity(){
//this method will be running on UI thread
ProviderServiceListFragment frag = new ProviderServiceListFragment();
frag.setArguments(args);
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame,
frag)
.commit();
}
I got a weird problem with an android activity : I re-used one of my previous activity that works well, but this time all I got is "Can't create handler inside thread that has not called Looper.prepare()"
I tried to debug, and everything in the async task is performing well but when I reach then end of onPostExecute() the error is raised.
So I tried to disable my process about the process dialog, the only change is that it's crashing on line upper.
Here is the code :
public class DateActivity extends ActionBarActivity{
ProgressDialog mProgressDialog;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_date);
ActionBar actionBar = this.getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setTitle(getResources().getString(R.string.actionbar_titre_date));
if (VerifConnexion.isOnline(this)) {
this.mProgressDialog = ProgressDialog.show(this, getResources().getString(R.string.loading),
getResources().getString(R.string.loading), true);
new QueryForDateTask().execute(this.mProgressDialog, this, this.getApplicationContext());
} else {
...
}
});
alertDialog.show();
}
}
private class QueryForDateTask extends
AsyncTask<Object, Void, ArrayList<String>> {
private ProgressDialog mProgressDialog;
private Activity act;
private Context context;
protected ArrayList<String> doInBackground(Object... o) {
this.mProgressDialog = (ProgressDialog) o[0];
this.act = (Activity) o[1];
this.context = (Context) o[2];
ArrayList<String> listeDate = this.parseJSON(this.startQuerying());
return listeDate;
}
public JSONObject startQuerying() {
JSONRequest jr = new JSONRequest();
String from = getResources().getString(R.string.api_param_from);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.FRANCE);
from += "=" + sdf.format(new Date());
String url = getResources().getString(
R.string.api_dates_json);
JSONObject jo = jr.getJSONFromUrl(url + "?" + from);
return jo;
}
public ArrayList<String> parseJSON(JSONObject jsonObject) {
ArrayList<String> l = new ArrayList<String>();
try {
JSONArray array = jsonObject.getJSONArray("dates");
if (array != null) {
for (int i = 0; i < array.length(); i++) {
String type = array.getString(i);
l.add(type);
} // fin parcours JSONArray
}
} catch (Exception _e) {
}
return l;
}
protected void onProgressUpdate(Integer... progress) {
// setProgressPercent(progress[0]);
}
protected void onPostExecute(ArrayList<String> lDate) {
// Create items for the ListView
DateAdapter adapter = new DateAdapter(this.context, R.layout.searchitem_date, lDate, this.act);
// specify the list adaptor
((ListView)findViewById(R.id.list)).setAdapter(adapter);
this.mProgressDialog.dismiss();
}
} // fin async
}
I tried this to replace the call to the AsyncTask :
runOnUiThread(new Runnable() {
public void run() {
QueryForDateTask task = new QueryForDateTask();
task.execute(DateActivity.this.mProgressDialog, DateActivity.this, DateActivity.this.getApplicationContext());
}
});
(like explained in Asynctask causes exception 'Can't create handler inside thread that has not called Looper.prepare()' as far as I understood), but the result is exactly the same.
So I can't understand why it is not working in this activity despite all is ok for the other ones of the project.
Any clue ?
Thank a lot for all ideas :)
Just a post to mark the trouble as resolved :
the adapter i used was buggy in parsing parameters and throwed a NullPointerException.
I just fixed it, the AsyncTask is now running without problem.
An Activity (SignInActivity) is calling a method in FunkcjeAPI which execute an AsyncTask.
My AsyncTask should show a ProgressDialog using an calling Activity. I don't know how to give it an correct Activity to the constructor. I tried a lot of thing, read a lot of tutorials and questions on SO, but I can't find solution. FunkcjeAPI isn't an Activity so I can't write new Logowanie(this).execute(argumenty);
AsyncTask calling code :
public class FunkcjeAPI {
static String dozwrotu = null;
public static String zalogujSie(final String nick, final String haslo)
{
String[] argumenty = {nick, haslo};
new Logowanie(/* WHAT HERE ? */).execute(argumenty); // HELP ME IN THAT LINE !!!!!!!!!!!!!
return dozwrotu;
}
My AsyncTask class code (it is in FunkcjeAPI class):
private class Logowanie extends AsyncTask<String, Void, String>
{
Activity wywolujaceActivity;
public Logowanie(Activity wywolujaceActivity) {
this.wywolujaceActivity = wywolujaceActivity;
}
#SuppressWarnings("deprecation")
#Override
protected void onPreExecute() {
wywolujaceActivity.showDialog(SignInActivit.PLEASE_WAIT_DIALOG);
}
#Override
protected String doInBackground(final String... argi) {
final JSONParser jParser = new JSONParser();
new Thread(new Runnable() {
public void run() {
final String json = jParser.getJSONFromUrl("http://tymonradzik.pl/THUNDER_HUNTER/thapi.php?q=login&username=" + argi[0] + "&password=" + argi[1] + "&imei=");
Handler mainHandler = new Handler(Looper.getMainLooper());
mainHandler.post(new Runnable() {
#Override
public void run() {
JSONObject jObject;
try {
jObject = new JSONObject(json);
Log.wtf("Link", "http://tymonradzik.pl/THUNDER_HUNTER/thapi.php?q=login&username=" + argi[0] + "&password=" + argi[1] + "&imei=");
Log.wtf("Link", json);
String error = jObject.getString("error");
if(error == "You reached daily query limit !") { nadajWartosc("You reached daily query limit !"); }
if(error == "0") {nadajWartosc(jObject.getString("token"));}
if(error == "1") {nadajWartosc("1");}
if(error == "Invalid username") {nadajWartosc("Invalid username");}
if(error == "Invalid password") {nadajWartosc("Invalid password");}
if(error == "This user is already logged in !") {nadajWartosc("This user is already logged in !");}
} catch (JSONException e1) {
e1.printStackTrace();
}
catch (NullPointerException e)
{
e.printStackTrace();
}
}
});
}}).start();
return dozwrotu;
}
#Override
protected void onPostExecute(String result) {
wywolujaceActivity.removeDialog(SignInActivit.PLEASE_WAIT_DIALOG);
}
}
Add one more parameter to zalogujSie() method that takes an Activity, and then use this parameter to start the AsyncTask:
public static String zalogujSie(Activity activity, final String nick, final String haslo)
{
// .....
new Logowanie(activity).execute(argumenty);
return dozwrotu;
}
Then you would call this method from the activity like this:
FunkcjeAPI.zalogujSie(this, "Nick", "Haslo");
I'm having a this error Only the original thread that created a view hierarchy can touch its views.
But i don't know how to handle the ui in multithread, like list view and i don't know where to put it.
// Download JSON in Background
public class DownloadJSONFileAsync extends AsyncTask<String, Void, Void> {
protected void onPreExecute() {
super.onPreExecute();
showDialog(DIALOG_DOWNLOAD_JSON_PROGRESS);
}
#Override
protected Void doInBackground(String... params) {
deviceId = generateDeviceId();
elementsList.add(new BasicNameValuePair("DeviceID", deviceId));
JSONObject json = jsonParser.makeHttpRequest(
url_get_reports, "POST", elementsList);
Log.d("Create Response", json.toString());
// check for success tag
try {
int success = json.getInt(TAG_SUCCESS_REPORT);
// successfully created
// getting JSON string from URL
try {
if (success == 1) {
reports = json.getJSONArray(TAG_Report);
report_data = new Report[reports.length()];
// looping through All Products
for (int i = reports.length()-1; i >= 0; i--) {
JSONObject c = reports.getJSONObject(i);
reportID = c.getString("reportID");
Drawable drawable = LoadImageFromWeb(url+c.getString(TAG_IMAGE));
String state = "";
if(c.getString("state").equals("1")){
state = "Pinding";
}else if(c.getString("state").equals("2")){
state = "Inprogress";
}else{
state = "Completed";
}
if(c.getString(TAG_TITLE).equals("")){
report_data[i] = new Report(reportID,"Report "+(i+1),c.getString(TAG_TIME),drawable,url+c.getString(TAG_IMAGE),state,c.getString("coordination")) ;
}else{
report_data[i] = new Report(reportID,c.getString(TAG_TITLE),c.getString(TAG_TIME),drawable,url+c.getString(TAG_IMAGE),state,c.getString("coordination"));
}
if(json.getInt("successReplies")==1){
replies = json.getJSONArray(TAG_REPLIES);
ArrayList<String> arr = new ArrayList<String>();
for(int j=0;j<replies.length();j++){
JSONObject c2 = replies.getJSONObject(j);
if(reportID.equals(c2.getString("ReportID")))
{
arr.add(c2.getString("RepliesContent")+"\n"+c2.getString("RepliesTime"));
}
}
report_data[i].setRepliesArray(arr);
}
}
list = (ListView)findViewById(R.id.list);
ReportAdapter adapter = new ReportAdapter(Display_Reports.this,report_data);
list.setAdapter(adapter);
// Click event for single list row
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(
AdapterView<?> arg0, View arg1,
int position, long id) {
Intent intent = new Intent(Display_Reports.this, Display_Report_Details.class);
intent.putExtra("ID", report_data[position].ID);
intent.putExtra("Name", report_data[position].Name);
intent.putExtra("State", report_data[position].State);
intent.putExtra("Time", report_data[position].Time);
intent.putExtra("ImageUrl", report_data[position].ImageUrl);
intent.putExtra("Coordination", report_data[position].Coordination);
intent.putStringArrayListExtra("RepliesContent", report_data[position].getRepliesArray());
startActivity(intent);
}
});
} else {
// no Entities found
Toast.makeText(Display_Reports.this, "No reports found",
Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Void unused) {
dismissDialog(DIALOG_DOWNLOAD_JSON_PROGRESS);
removeDialog(DIALOG_DOWNLOAD_JSON_PROGRESS);
}
}
You cannot modify the UI from a background thread. Whether you use AsyncTask, or a Handler, or runOnUiThread(), or post(), to have work done on the main application thread is up to you.
You may wish to review the documentation on threads and some of these techniques.