I'm trying to develop an android app that could list all app and their cache's.
But I'm facing a problem that whenever I tap on generated list I'm getting force close because
java.lang.IllegalStateException: The content of the adapter has
changed but ListView did not receive a notification.
Make sure the content of your adapter is not modified from a background thread,
but only from the UI thread.
So I'm trying to convert my AsyncTask code to Thread Hadler, can any body please help me out with this problem. Here is my code
public class Messages extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
msgList = (ListView) findViewById(R.id.MessageList);
applicationCacheSize = new ArrayList<Long>();
applicationPackageName = new ArrayList<String>();
applicationName = new ArrayList<String>();
cacheApplicationName = new ArrayList<String>();
details = new ArrayList<MessageDetails>();
new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
pd = ProgressDialog.show(Messages.this, "Loading..",
"Please Wait", true, false);
}// End of onPreExecute method
#Override
protected Void doInBackground(Void... params) {
for (ApplicationInfo packageInfo : packages)
{
try
{
Context mContext = createPackageContext(packageInfo.packageName, CONTEXT_IGNORE_SECURITY);
PackageManager pm = mContext.getPackageManager();
ApplicationInfo ai;
try {
ai = pm.getApplicationInfo( mContext.getPackageName(), 0);
} catch (final NameNotFoundException e) {
ai = null;
}
final String applicationName = (String) (ai != null ? pm.getApplicationLabel(ai) : "(unknown)");
appNames.add(applicationName);
appPackageName.add(packageInfo.packageName);
appCache.add(mContext.getCacheDir());
}
catch (NameNotFoundException e)
{
e.printStackTrace();
}
}
for(int i=0; i<appCache.size(); i++)
{
try {
final PackageManager pm = getPackageManager();
Method getPackageSizeInfo;
getPackageSizeInfo = pm.getClass().getMethod(
"getPackageSizeInfo", String.class, IPackageStatsObserver.class);
getPackageSizeInfo.invoke(pm, appPackageName.get(i), new IPackageStatsObserver.Stub() {
#Override
public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
throws RemoteException {
final String title;
ApplicationInfo applicationInfo;
try {
applicationInfo = pm.getApplicationInfo(pStats.packageName, 0);
title = (String)((applicationInfo != null) ? packageManager.getApplicationLabel(applicationInfo) : "???");
MessageDetails Detail;
Detail = new MessageDetails();
Detail.setIcon(getPackageManager().getApplicationIcon( pStats.packageName ));
Detail.setName(title);
Detail.setSub("Cache Size -> "+(((pStats.cacheSize/1024) > 0)?(pStats.cacheSize/1024):"No Cache"));
details.add(Detail);
if((pStats.cacheSize) != 0 )
{
cacheApplicationName.add(title);
}
} catch (final NameNotFoundException e) {}
}
});
}
catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}// End of doInBackground method
#Override
protected void onPostExecute(Void result) {
CustomAdapter adapter = new CustomAdapter(details, Messages.this);
msgList.setAdapter(adapter);
pd.dismiss();
}// End of onPostExecute method
}.execute((Void[]) null);
}
}
Thanks in advance.
First, do not use detail = new Asyntasck. Create The Asynctask Class below and just use :
AsynTask myTask = new AsynTask();
myTask.execute();
Then your adapter is actually modified from a background thread (asynctask), exactly as the exception suggested. The solution is moving it to UI thread or simply wrapping it with runOnUiThread():
... ...
runOnUiThread(new Runnable() {
public void run() {
details.add(result) //use a foreach here
CustomAdapter adapter = new CustomAdapter(details, Messages.this);
adapter.notifyDataSetChanged();
msgList.setAdapter(adapter);
pd.dismiss();
}
}); // end of runOnUiThread
... ...
Related
I want to use progress bar... but As I searched, progress bar can not use with Asynctask.get.But I have to use .get and progress in Asynctask.
I made very simple source.
How can I changed to show progress bar in main thread??
I want to use both get method and ui progress.
public void onCreate(Bundle savedInstanceState) {
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
AAA asyncTask = new AAA();
try {
((AAA) asyncTask).execute(null, null, null,null).get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
public class AAA extends AsyncTask<Object, String, Object> {
private ProgressDialog progDailog = null;
#Override
protected void onPreExecute() {
super.onPreExecute();
progDailog = new ProgressDialog(ViewTestActivity.this);
progDailog.setMessage("Loading...");
progDailog.setIndeterminate(false);
progDailog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progDailog.setCancelable(true);
progDailog.show();
}
#Override
protected Object doInBackground(Object... params) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return params;
}
#Override
protected void onPostExecute(Object result) {
progDailog.dismiss();
}
}
Please help me.
Thanks!!
Do it before calling AsyncTask
private ProgressDialog progDailog = null;
public void onCreate(Bundle savedInstanceState) {
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
AAA asyncTask = new AAA();
try {
progDailog = new ProgressDialog(ViewTestActivity.this);
progDailog.setMessage("Loading...");
progDailog.setIndeterminate(false);
progDailog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progDailog.setCancelable(true);
progDailog.show();
((AAA) asyncTask).execute(null, null, null,null);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
public class AAA extends AsyncTask<Object, String, Object> {
#Override
protected Object doInBackground(Object... params) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return params;
}
#Override
protected void onPostExecute(Object result) {
progDailog.dismiss();
}
}
I don't know if there's a standard answer, but I've just done something very similar by setting up listener on the main thread, and sending progress messages to the listener from the async task - actually in my case it was loading asynchronously from a database. Works fine for me.
Try with this :
private ProgressDialog progDailog;
public void onCreate(Bundle savedInstanceState) {
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
progDailog = new ProgressDialog(ViewTestActivity.this);
progDailog.setMessage("Loading...");
progDailog.setIndeterminate(false);
progDailog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progDailog.setCancelable(true);
progDailog.show();
AAA asyncTask = new AAA(progDialog);
try {
((AAA) asyncTask).execute(null, null, null,null).get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
public class AAA extends AsyncTask<Object, String, Object> {
private ProgressDialog progressDialog;
public AAA (ProgressDialog progressDialog) {
this.progressDialog = progressDialog;
}
#Override
protected Object doInBackground(Object... params) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return params;
}
#Override
protected void onPostExecute(Object result) {
progressDialog.dismiss();
}
}
you should update your progress bar percentage in onProgressUpdate
See this example AsyncTask with progress bar
This question already has an answer here:
What is the simplest way in Android to keep an objects value after every app run?
(1 answer)
Closed 7 years ago.
I have an android chat application that sends messages from client to server but I am looking for a way to store the send messages in some way, other than being displayed in the list.
Here is part of my application;
public class AndroidChatApplicationActivity extends Activity {
private Handler handler = new Handler();
public ListView msgView;
public ArrayAdapter<String> msgList;
// public ArrayAdapter<String> msgList=new ArrayAdapter<String>(this,
// android.R.layout.simple_list_item_1);;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
msgView = (ListView) findViewById(R.id.listView);
msgList = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1);
msgView.setAdapter(msgList);
// msgView.smoothScrollToPosition(msgList.getCount() - 1);
Button btnSend = (Button) findViewById(R.id.btn_Send);
receiveMsg();
btnSend.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final EditText txtEdit = (EditText) findViewById(R.id.txt_inputText);
// msgList.add(txtEdit.getText().toString());
sendMessageToServer(txtEdit.getText().toString());
msgView.smoothScrollToPosition(msgList.getCount() - 1);
}
});
Button twitterButton = (Button) findViewById(R.id.website_Button);
twitterButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sendToWebsite();
}
});
}
protected void sendToWebsite() {
String url = "https://www.ljmu.ac.uk/";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
}
// receiveMsg();
// ----------------------------
// server msg receieve
// -----------------------
// End Receive msg from server//
public void sendMessageToServer(String str) {
final String str1 = str;
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
// String host = "opuntia.cs.utep.edu";
String host = "10.0.2.2";
String host2 = "127.0.0.1";
PrintWriter out;
try {
Socket socket = new Socket(host, 8008);
out = new PrintWriter(socket.getOutputStream());
// out.println("hello");
out.println(str1);
Log.d("", "test");
out.flush();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("", "test2");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("", "test3");
}
}
}).start();
}
public void receiveMsg() {
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
// final String host="opuntia.cs.utep.edu";
final String host = "10.0.2.2";
// final String host="localhost";
Socket socket = null;
BufferedReader in = null;
try {
socket = new Socket(host, 8008);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (true) {
String msg = null;
try {
msg = in.readLine();
Log.d("", "MSGGG: " + msg);
// msgList.add(msg);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (msg == null) {
break;
} else {
displayMsg(msg);
}
}
}
}).start();
}
public void displayMsg(String msg) {
final String mssg = msg;
handler.post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
msgList.add(mssg);
msgView.setAdapter(msgList);
msgView.smoothScrollToPosition(msgList.getCount() - 1);
Log.d("", "Hi Test");
}
});
}
}
Could anyone suggest a method of storing the messages other than displaying them in a list?
You can try storing them in SharedPreferences. By what I gather, you want store the input so that you can later look at then in a different activity. Have a look at SharedPreferences here http://developer.android.com/reference/android/content/SharedPreferences.html
I am trying to create an Android library which provides AsyncTask operations. I created my AsyncTask as below. However, I don't know how to access library's resources. The context field is set by the activity who uses that library. I used to access the resources by calling getActivity().getResources(). But this AsyncTask's context comes from the project that uses it and I don't know how to access the library's resources. How can I achieve that?
public class CheckBalanceAsyncTask extends AsyncTask<Void, Void, Void> {
private Context mContext;
String json;
JSONObject jsonObject,jsonObjResult;
JSONArray jsonArray;
String message,balance;
ProgressDialog progress;
public CheckBalanceAsyncTask (Context context){
mContext = context;
//progress = new ProgressDialog(mContext);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
// progress.setCancelable(false);
// progress.setMessage("please wait");//getString(R.string.pleasewait));
// progress.setTitle("waiting");//getString(R.string.loading));
// progress.setIcon(R.drawable.ic);
// progress.setProgressStyle(ProgressDialog.STYLE_SPINNER);
// progress.setProgress(0);
// progress.setMax(100);
// progress.show();
}
#Override
protected Void doInBackground(Void... params) {
String aliasNo = "";
PackageInfo pinfo = null;
try {
pinfo = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0);
} catch (NameNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String versionName = pinfo.versionName;
String cardServiceUrl = "blabla";
Log.e("LOGGGGG", cardServiceUrl);
try {
json = JSONParser.getJSONFromUrl(cardServiceUrl);
try {
jsonObject = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser",
"Error creating json object" + e.toString());
}
jsonArray = jsonObject.getJSONArray("cardlist");
jsonObjResult = jsonObject.getJSONObject("result");
message = jsonObjResult.get("message").toString();
Log.e("MESSAGE", "" + message);
JSONObject row = jsonArray.getJSONObject(0);
balance = row.optString("balance");
}
catch (JSONException e) {
Log.e("json", "doInBackground2");
}
return null;
}
#Override
protected void onPostExecute(Void args) {
//progress.dismiss();
try {
if (jsonObjResult.get("message").toString()
.equalsIgnoreCase("ok")) {
Toast.makeText(mContext, balance+" TL", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Ressources are automatically merged with the main application then, no need to do something specific to access string, drawable, layout, etc...
getActivity().getResources() will work fine.
I'm trying to implement an asynchronous access to internet using AsyncTask, but in log cat PID and TID of my logging are the same, because AsyncTask doesn't create a parallel queue, so my app crashes with a NetworkOnMainThreadException.
Here's my subclass code :
class BL_SimpleAsyncTask extends AsyncTask<Void, Void, Void> {
String requestServer;
HashMap<String, String> postRequestBody;
//------------------------// answer from http client
static DefaultHttpClient sharedClient = null;
boolean isPostRequest;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
System.out.println("bg started");
if (sharedClient == null) {
sharedClient = new DefaultHttpClient();
}
HttpPost post = new HttpPost(requestServer);
String postBody = new String();
postBody += "{";
for (String key : postRequestBody.keySet()) {
String result = String.format("\"%s\":\"%s\",", key, postRequestBody.get(key));
postBody += result;
}
System.out.println("body initialized");
postBody.substring(0, postBody.length() - 1);
postBody += "}";
try {
post.setEntity(new StringEntity(postBody));
} catch (UnsupportedEncodingException e) {
System.out.println(e.getMessage());
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("entity set");
try {
if (post != null) {
System.out.println("starting request....");
HttpResponse response = sharedClient.execute(post);
System.out.println("responce recieved");
} else {
System.out.println("null request");
}
// System.out.println(response) ;
} catch (ClientProtocolException e) {
System.out.println(e.getMessage());
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
System.out.println(e.getMessage());
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
}
So, to start post-request, I simply do the following :
BL_SimpleAsyncTask obj = new BL_SimpleAsyncTask() ;
obj.requestServer = "https://api.orbios.com/v1/auth/sign-in" ;
obj.postRequestBody = new HashMap<String, String> () ;
obj.postRequestBody.put ("password", password) ;
obj.postRequestBody.put("email", email ) ;
obj.isPostRequest = true ;
System.out.println("start bg thread") ;
obj.doInBackground() ;
What am I doing wrong?
You are not supposed to call doInBackground() yourself. Just call execute() and let the framework call your doInBackground() in a background thread.
Instead of calling directly doInBackground() you should be calling execute method.
I have written a code to download some data from internet. Than i wanted to put it into asyncTask. And after that downloading stopped working. It looks like it cant finish try{} part so skips to exeption.
From main activity "Nekaj" i call loadData() class, which extends AsyncData. From there i call "oto" class inside try command. "oto" class is used to read stuff from internet and returns array of strings. This worked when i called oto class directly from "Nekaj"class. What did I do wrong with using AsyncTask?
Here is the code:
public class Nekaj extends Activity {
TextView Tkolo, Tbroj1;
String[] brojevi_varijabla;
String privremena_varijabla = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.bez_provjere_739);
Tkolo = (TextView) findViewById(R.id.Xkolo);
Tbroj1 = (TextView) findViewById(R.id.Xbroj1);
/*
* try { privremena_varijabla = test.kolo_739();
* Tkolo.setText(privremena_varijabla); } catch (Exception e) { // TODO
* Auto-generated catch block e.printStackTrace(); }
*/
new loadData().execute();
}
public class loadData extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
Oto test = new Oto();
try {
brojevi_varijabla = test.brojevi_739();
if (Integer.valueOf(brojevi_varijabla[0]) > 10) {
Tbroj1.setText("" + brojevi_varijabla[0]);
} else {
Tbroj1.setText(" " + brojevi_varijabla[0]);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
public class Oto {
public String[] brojevi_739() throws Exception {
int i = 0;
int uvjet = 0;
int varijabla = 0;
char[] znak = { '>', '<' };
BufferedReader in = null;
String data[] = null;
String provjera = "date-info";
int[] polje = new int[2];
try {
HttpClient klijent = new DefaultHttpClient();
URI webstranica = new URI(
"https://www.aaa.bb");
HttpGet zahtjev = new HttpGet();
zahtjev.setURI(webstranica);
HttpResponse odgovor = klijent.execute(zahtjev);
in = new BufferedReader(new InputStreamReader(odgovor
.getEntity().getContent()));
StringBuffer brojevi = new StringBuffer("");
String brojevi_string = null;
String neki_string = null;
String red = "";
in.skip(21000);
while ((red = in.readLine()) != null) {
varijabla = red.indexOf(provjera);
if (varijabla != -1) {
// 1. KOLO
if (uvjet == 0) { // onda sadrži taj
// substring
// !!!!
red = in.readLine(); // sada string red sadrži ono
// što
// želim, još moram samo to
// izrezati!!
do {
if (i == 0) {
varijabla = red.indexOf(znak[i]);
}
else {
varijabla = red.indexOf(znak[i], polje[0]);
}
if (varijabla != -1) // ako taj znak postoji u
// stringu
{
if (i == 0) {
polje[i] = varijabla + 1;
}
else {
polje[i] = varijabla;
}
i++;
}
} while (i <= 1);
neki_string = red.substring(polje[0], polje[1]);
Tkolo.setText(neki_string);
provjera = "Dobitna kombinacija";
uvjet++;
continue;
}
}
}
in.close();
brojevi_string = brojevi.toString();
data = brojevi_string.split("\n");
return data;
} finally {
if (in != null) {
try {
in.close();
return data;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}}
What you are doing wrong is Tbroj1.setText() inside the doInBackground() method. What you have to do is to use the onPostExecute method to post your data on the UI:
public class loadData extends AsyncTask<String, Integer, Boolean> {
protected Long doInBackground(String... arg0) {
Oto test = new Oto();
Boolean result = false;
try {
brojevi_varijabla = test.brojevi_739();
result = true;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
protected void onPostExecute(Boolean result) {
if(result){
if (Integer.valueOf(brojevi_varijabla[0]) > 10) {
Tbroj1.setText("" + brojevi_varijabla[0]);
} else {
Tbroj1.setText(" " + brojevi_varijabla[0]);
}
}
}
}
Actually, You are trying to update UI in doInBackGround() of your AsyncTask, so its not allowed (doInBack.. runs in non UI Thread..), So put the UI updation code in onPostExecute() of AsyncTask..
Try this and let me know what happen..
public class loadData extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
Oto test = new Oto();
try {
brojevi_varijabla = test.brojevi_739();
if(brojevi_varijabla != null)
return brojevi_varijabla[0];
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result)
{
if(result != null)
{
if (Integer.valueOf(result) > 10) {
Tbroj1.setText("" + result;
} else {
Tbroj1.setText(" " + result);
}
}
}
}
use onPostExecute(Void result1) {}
to catch the result and perform the action required over there
You can't manipulate UI elements directly on a non-UI (background) thread, which is where doInBackground() always runs. The usual way of using AsyncTask is to get the data in doInBackground(), return it as a value, and then process the UI changes in onPostExecute(). For example:
public class loadData extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... arg0) {
Oto test = new Oto();
try {
brojevi_varijabla = test.brojevi_739();
if (Integer.valueOf(brojevi_varijabla[0]) > 10) {
return "" + brojevi_varijabla[0];
} else {
return " " + brojevi_varijabla[0];
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (result != null) Tbroj1.setText(result);
}
}