I am facing an issue in Async task, can anyone please suggest me any solution.
I have downloaded this example from this link :
Source
My Current Structure is
Main Class extends MyTask and implements AsyncTaskCompleteListener interface.
AsyncTaskCompleteListener is an Interface contains the onTaskComplete Method .
MyTask extends Async Task and onPostExcute contains CallBackMethod which will return the result-set got from the doInBackground.
Http Class(Utils) contains the Http connection and returns the Result-set to AsyncTaskComleteListner from PostExecute.
I am trying to get my result-set Value in the main class from the interface method to perform my further operation.
I tried to get the value from static variables, static method but non of them worked, and also tried with creating a new class object to send and receive the result but every time it gives me NullPointerException . Because the statement written after the AsyncTask gets executes before getting the result.
I have also tried to get the Status of asyncTask from its method getStaus(), but it returns only Running and dose not notify when the task is completed or finished.
Here is the code sample:
Main Class Code :
package com.example.androidasynctask;
public class MainActivity extends Activity implements AsyncTaskCompleteListener {
public static String[] asyncResult;
String res[] = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void btnclick(View view) {
/*MyTask asyncTask = new MyTask(this);
String [] asyncTaskResult = asyncTask.execute("fetchCategory.php","1%Id%1");*/
//AsyncTask<String, Void, String[]> asyncTaskRes = new MyTask(this).execute("fetchCategory.php","1%Id%1");
//new MyTask(this).execute("fetchCategory.php","1%Id%1");
MyTask asyncTask = (MyTask) new MyTask(this).execute("fetchCategory.php","1%Id%1");
if(asyncTask.getStatus().equals(AsyncTask.Status.FINISHED) || asyncTask.getStatus().equals(AsyncTask.Status.PENDING)) {
asyncTask.execute();
}
else {
Log.v("In Else","Get Value");
}
}
#Override
public void onTaskComplete(String[] result) {
Log.v("IN ON TASK COMPLETE","VALUE = "+result[1]);
}
/*#Override
public void onTaskComplete(String result) {
System.out.println("calling onTaskComplete SIMPLE....");
System.out.println("result :: "+ result);
}*/
public static class GetAsyncResult
{
static String[] returnValues;
public GetAsyncResult()
{}
public GetAsyncResult(String[] res)
{
returnValues = res;
Log.v("getResultSetValues","returnValues"+returnValues[1]);
}
public void getResultSetValues()
{
Log.v("getResultSetValues","returnValues"+returnValues[1]);
}
}
}
Async Task Code :
public class MyTask extends AsyncTask<String, Void, String[]> {
private Activity activity;
private ProgressDialog dialog;
private AsyncTaskCompleteListener callback;
public String[] asyncResultSetValue = null;
public MyTask(Activity act) {
Log.v("MY TASK","ACTIVITY"+act);
this.activity = act;
this.callback = (AsyncTaskCompleteListener)act;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
Log.v("MY TASK","in ON PRE EXECUTE");
dialog = new ProgressDialog(activity);
dialog.setMessage("Loading...");
dialog.show();
}
#Override
protected String[] doInBackground(String... params) {
Log.v("MY TASK","DO IN BACKGROUND");
Log.v("PARAMS"," params[0] = "+params[0]+ "| params[1]"+params[1]);
asyncResultSetValue = Utils.process_query(params[0],params[1]);
return asyncResultSetValue;
}
#Override
protected void onPostExecute(String[] result) {
super.onPostExecute(result);
Log.v("MY TASK","in ON POST EXECUTE");
if (null != dialog && dialog.isShowing()) {
dialog.dismiss();
}
callback.onTaskComplete(result);
}
}
HTTP CLASS CODE :
public class Utils {
static String result = null;
String endResult;
static java.io.InputStream is = null;
static StringBuilder sb=null;
static String delimiter = "\\|";
static String delimiter1 = "\\%";
static String[] temp = null;
static String[] temp1 = null;
static ArrayList<NameValuePair> nameValuePairs;
static Context context;
static ProgressDialog mDialog;
static HttpResponse response;
static String[] resultset_value = null;
//static String url = "http://fortuneworkinprogress.in/News_App/"; //Global URL
static String url = "http://10.0.2.2/News_App/"; //Global URL
static String query_type,parameter;
/*************** PROCESS QUERY START ***************/
public static String[] process_query(String str_url, String parameter) {
// String strval = select_parameter;
String ret_val[] = null;
String get_sel_val[] = null;
int loopcount =0;
url = url+str_url; //!!!! ######### CONCATINATING AND CREATING FULL URL ######## !!!!!!//
Log.v("PROCESS QUERY PARAMETER","URL = "+url+" | PARAMTER = "+parameter);
nameValuePairs = new ArrayList<NameValuePair>();
//Log.i("STR VAL",""+strval); //To Check which values are recieved
try
{
String strval = parameter;
get_sel_val=strval.split(delimiter1);
for(int i =0; i < get_sel_val.length ; i++)
{
loopcount = Integer.parseInt(get_sel_val[0]); // First Delimeted Value which tells the number of count
Log.i("Loopcount","cnt = "+loopcount);
}
for(int j=1;j<=(loopcount*2);j=j+2) //For Loop for making Name Values Pares Dynamic
{
nameValuePairs.add(new BasicNameValuePair(get_sel_val[j],get_sel_val[j+1]));
//Log.i("J = ["+j+"]","pairvalue1 = "+get_sel_val[j]+"pairvalue2 ="+get_sel_val[j+1]);
}
}
catch(Exception e)
{
Log.w("Exception in the getting value","Exp = "+e);
}
//nameValuePairs.add(new BasicNameValuePair("id","1"));
try{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
Log.v("CONNECT URL ","Final url "+url);
Log.w("CONNECTION STATUS ",httppost.toString());
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
Log.w("PAERSE VALUE ",nameValuePairs.toString());
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
Log.w("1", "Connection establised succesfuly");
}
catch(Exception e)
{
Log.e("log_tag", "Error in http connection"+e.toString());
}
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
sb = new StringBuilder();
sb.append(reader.readLine() + "\n");
Log.v("SB VALUE = ","sb = "+sb.toString());
String line="0";
while ((line = reader.readLine()) != null)
{
sb.append(line + "\n");
}
is.close();
result=sb.toString();
// Toast.makeText(getBaseContext(), result ,Toast.LENGTH_LONG).show();
Log.w("result", result);
}
catch(Exception e)
{
Log.e("log_tag", "Error converting result "+e.toString());
Toast.makeText(null, "error converting response to string" ,Toast.LENGTH_LONG).show();
}
String[] temp = null;
String[] tempResult = null;
if(result!=null)
{
tempResult = result.split(delimiter); //Split the entire return string into "rows"
for(int i =0; i < tempResult.length-1 ; i++)
{
temp = null;
temp = tempResult[i].split(delimiter1); //Find columns for each row
ret_val = temp;
resultset_value=ret_val;
}
}
else
{
Toast.makeText(null, "Cannot Find Routes" ,Toast.LENGTH_LONG).show();
}
Log.v("BEFORE RETUNR = ","ret_val = "+ret_val.toString());
return ret_val; //Returning the result value array
}
/*************** PROCESS QUERY ENDS ***************/
public static boolean isNetworkAvailable(Activity activity)
{
ConnectivityManager connectivity = (ConnectivityManager) activity
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity == null)
{
return false;
}
else
{
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null)
{
for (int i = 0; i < info.length; i++) {
if (info[i].getState() == NetworkInfo.State.CONNECTED)
{
return true;
}
}
}
}
return false;
}
}
Thanks in advance.
Because the statement written after the AsyncTask gets executes before getting the result.
the reason is AsyncTask runs on separate thread,not on your Main(UI) thread.
MyTask extends Async Task and onPostExcute contains CallBackMethod which will return the result-set got from the doInBackground.
you will be getting result values on this method
#Override
public void onTaskComplete(String[] result) {
Log.v("IN ON TASK COMPLETE","VALUE = "+result[1]);
}
Comment following piece of code,
if(asyncTask.getStatus().equals(AsyncTask.Status.FINISHED) || asyncTask.getStatus().equals(AsyncTask.Status.PENDING)) {
asyncTask.execute();
}
else {
Log.v("In Else","Get Value");
}
Make change,
public static String[] asyncResult; to public String[] asyncResult = null;
Change following,
asyncResultSetValue = Utils.process_query(params[0],params[1]); to asyncResult = Utils.process_query(params[0],params[1]);
and return asyncResultSetValue; to return asyncResult ;
look at value by adding one more log,you will be getting result values on this method
#Override
public void onTaskComplete(String[] result) {
Log.v("IN ON TASK COMPLETE","VALUE = "+result[1]);
Log.v("IN ON TASK COMPLETE","VALUE = "+asyncResult[1]);
}
Related
[Update] Added repository link to download the project
I'm having this activity which connects to a URL to fetch data and display it using RecyclerView with a custom adapter. How can I edit this code to use AsyncTaskLoader instead of AsyncTask? here's the repository to download the very simple project Soonami tutorial app
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
public static QuakesAdapter quakesAdapter;
public static ArrayList<Event> eventsList = new ArrayList<>();
public static final String USGS_REQUEST_URL =
"https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=2018-01-01&endtime=2018-12-01&minmagnitude=6&limit=50";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recycler_view);
quakesAdapter = new QuakesAdapter(this, eventsList);
//defining recyclerView and setting the adapter
quakesAdapter.notifyDataSetChanged();
FetchData fetchData= new FetchData();
fetchData.execute();
}
private class FetchData extends AsyncTask<String, Void, ArrayList<Event>> {
String myDdata = "";
String line = "";
#Override
protected ArrayList<Event> doInBackground(String... params) {
try {
//opening the connection
if (httpURLConnection.getResponseCode() == 200) {
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
while(line != null){
line = bufferedReader.readLine();
myDdata = myDdata + line;
}
JSONObject jsonObject = new JSONObject(myDdata);
eventsList.clear();
JSONArray jsonArray = jsonObject.getJSONArray("features");
for(int i = 0; i < jsonArray.length(); i++){
//getting values of the 3 attributes
eventsList.add(new Event(title, time, tsunamiAlert));
}
if (inputStream != null) {
inputStream.close();
}
} else {
Log.e("Connection Error: ", "Error response code: " + httpURLConnection.getResponseCode());
}
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
}
catch (MalformedURLException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(ArrayList<Event> result) {
super.onPostExecute(result);
quakesAdapter.notifyDataSetChanged();
}
}
}
I have tested multiple examples but they have different codes and triggers multiple errors with my code like this one and still looking for a solution which makes my code works fine.
Set adpter in your recyclerview and then call the loader like this way:
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<Event>> {
{
private RecyclerView recyclerView;
public static QuakesAdapter quakesAdapter;
public static ArrayList<Event> eventsList = new ArrayList<>();
public static final String USGS_REQUEST_URL =
"https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=2018-01-01&endtime=2018-12-01&minmagnitude=6&limit=50";
#Override
protected void onCreate (Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recycler_view);
quakesAdapter = new QuakesAdapter(this, eventsList);
//defining recyclerView and setting the adapter
recyclerView.setAdapter(quakesAdapter);
getSupportLoaderManager().initLoader(1, null, this).forceLoad();
}
#Override
public Loader<List<Event>> onCreateLoader ( int id, Bundle args){
return new FetchData(MainActivity.this);
}
#Override
public void onLoadFinished (Loader < List < Event >> loader, List < Event > data){
quakesAdapter.setData(data);
}
#Override
public void onLoaderReset (Loader < List < Event >> loader) {
quakesAdapter.setData(new ArrayList<Event>());
}
Performs actual task in background and returns the result.
private static class FetchData extends AsyncTaskLoader<List<Event>>{
String myDdata = "";
String line = "";
public FetchData(Context context) {
super(context);
}
#Override
public List<Event> loadInBackground () {
try {
List<Event> list = new ArrayList<Event>();
//opening the connection
if (httpURLConnection.getResponseCode() == 200) {
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
while (line != null) {
line = bufferedReader.readLine();
myDdata = myDdata + line;
}
JSONObject jsonObject = new JSONObject(myDdata);
JSONArray jsonArray = jsonObject.getJSONArray("features");
for (int i = 0; i < jsonArray.length(); i++) {
//getting values of the 3 attributes
eventsList.add(new Event(title, time, tsunamiAlert));
}
if (inputStream != null) {
inputStream.close();
}
} else {
Log.e("Connection Error: ", "Error response code: " + httpURLConnection.getResponseCode());
}
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
return eventsList;
}
}
Add a method in your adapter like this:
public void setData(List<Event> data) {
this.data=data;
notifyDataSetChanged();
}
Which kind of error do you encounter?
I suggest using Java Interface and CallBack method for your AsynkTask, in this scenario, whenever your AsynkTask task is done, it notify the Activity with that callback method and you can execute notifyDataSetChange method of the adapter.
I have an app that connects to server sends sql request and get JSON answer as JsonArray.
Its Asynktask in seperate class (HTTPRequest.java is my AsyncTask class, Responce.java its my callback interface class) and it works correct.
when I use it in OrderActivity.java like below
#Override //my interface class function
public void onPostExecute(JSONArray Result) {
load(Result);
}
private void load(JSONArray json) {
for(int i=0;i<json.length();i++){
try {
JSONObject jo = json.getJSONObject(i);
Product p = new Product(
jo.getInt("ID"),
jo.getInt("parent"),
jo.getInt("category"),
jo.getString("Item"),
jo.getDouble("Price")
);
products.add(p);
} catch (JSONException e) {
e.printStackTrace();
}
}
it does work and fills product with data, but when I assign to my class variable JSONArray json
JSONArray json = new JSONArray;
.
.
.
#Override
public void onPostExecute(JSONArray Result) {
json = Result;
}
json is null
//HTTPRequest.java
public class HTTPRequest extends AsyncTask<String, Void, Integer> {
private Context context;
private Responce responce;
JSONArray json;
public HTTPRequest(Context context){
this.context = context;
responce = (Responce)context;
}
#Override
protected Integer doInBackground(String... params) {
OutputStream output;
InputStream inputStream = null;
HttpURLConnection connection = null;
String charset = "UTF-8";
Integer result = 0;
try {
URL uri = new URL(params[0]);
connection = (HttpURLConnection) uri.openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Accept-Charset", charset);
connection.setRequestProperty("Content-Type", "text/plain; charset=" + charset);
output = connection.getOutputStream();
output.write(params[1].getBytes(charset));
output.close();
int statusCode = connection.getResponseCode();
if (statusCode == 200) {
inputStream = new BufferedInputStream(connection.getInputStream());
json = new JSONArray(getJSON(inputStream));
result = 1;
}
} catch (Exception e) {
e.getLocalizedMessage();
}
return result;
}
#Override
protected void onPostExecute(Integer i) {
super.onPostExecute(i);
if(i == 1) {
responce.onPostExecute(json);
} else {
responce.onPostExecute(null);
}
}
private String getJSON(InputStream inputStream) throws IOException, JSONException {
StringBuffer stringBuffer = new StringBuffer();
BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(inputStream));
String line = "";
String result = null;
while((line = bufferedReader.readLine()) != null) {
stringBuffer.append(line.toString());
}
result = stringBuffer.toString();
if(null!=inputStream){
inputStream.close();
}
return result;
}
}
//Responce.java
public interface Responce {
public void onPostExecute(JSONArray Result);
}
//OrderActivity.java
public class OrderActivity extends Activity implements Responce{
ArrayList<Product> products = new ArrayList<Product>();
ProductAdapter productAdapter;
OrderItemAdapter orderItemAdapter;
ListView orderlist;
JSONArray ja;
Button btnBack;
Button btnTakeOrder;
ListView picklist;
HTTPRequest httpRequest;
String url = "http://192.168.3.125:8888/data/";
String query = "select * from vwitems order by category desc";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_order);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
orderlist =(ListView)findViewById(R.id.orderlist);
orderItemAdapter = new OrderItemAdapter(OrderActivity.this);
btnBack = (Button)findViewById(R.id.btnBack);
btnBack.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
productAdapter.filter(0);
}
});
btnTakeOrder = (Button)findViewById(R.id.btnTakeOrder);
btnTakeOrder.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Integer oid = 0;
Order order = new Order(OrderActivity.this);
oid = order.NewOrder(1, 2, 3);
Toast.makeText(OrderActivity.this," " + order.getCount(), LENGTH_SHORT).show();
}
});
orderlist.setAdapter(orderItemAdapter);
picklist = (ListView) findViewById(R.id.picklist);
picklist.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
int pid = 0;
if (productAdapter.getItem(position).isCategory()) {
pid = productAdapter.getItem(position).getId();
productAdapter.filter(pid);
} else {
OrderItem oi = new OrderItem();
oi.setItemId(productAdapter.getItem(position).getId());
oi.setItem(productAdapter.getItem(position).getItem());
oi.setPrice(productAdapter.getItem(position).getPrice());
search(oi);
}
}
});
httpRequest = new HTTPRequest(this);
httpRequest.execute(url, query);
}
private boolean search(OrderItem oi){
int size = orderItemAdapter.getCount();
int i = 0;
if(size != 0)
for(OrderItem o : orderItemAdapter.getAll()){
if(o.getItemId() == oi.getItemId()){
orderItemAdapter.getItem(i).setQuantity(orderItemAdapter.getItem(i).getQuantity() + 1);
orderItemAdapter.notifyDataSetChanged();
return true;
}
i++;
}
orderItemAdapter.addItem(oi);
orderItemAdapter.notifyDataSetChanged();
return false;
}
private void load(JSONArray json) {
for(int i=0;i<json.length();i++){
try {
JSONObject jo = json.getJSONObject(i);
Product p = new Product(
jo.getInt("ID"),
jo.getInt("parent"),
jo.getInt("category"),
jo.getString("Item"),
jo.getDouble("Price")
);
products.add(p);
} catch (JSONException e) {
e.printStackTrace();
}
}
productAdapter = new ProductAdapter(OrderActivity.this, products);
picklist.setAdapter(productAdapter);
productAdapter.filter(0);
}
#Override
public void onPostExecute(JSONArray Result) {
load(Result);
}
/*
#Override
public void onPostExecute(JSONArray Result) {
json = Result;
}
**/
}
sorry i forgot include this one
//Order.java
public class Order implements Responce{
private Context context;
private JSONArray json = new JSONArray();
private HTTPRequest httpRequest;
private int OrderID;
private Date OrderDate;
private int OrderTable;
private int Waiter;
private byte OrderStatus;
private List<OrderItem> orderItems;
public Order(Context context){
this.context = context;
}
//some code here...
public Integer NewOrder(Integer guests, Integer waiter, Integer ordertable){
String query = "insert into orders(orderdate, guests, waiter, ordertable) VALUES(NOW()," + guests + ", " + waiter + ", " + ordertable + "); SELECT LAST_INSERT_ID() as ID;";
Integer result = 0;
Connect(query);
try {
JSONObject jo = json.getJSONObject(0);
result = jo.getInt("ID");
} catch (JSONException e) {
e.printStackTrace();
}
return result; //here i got 0 if i init result to 0, null or what ever i init my
}
#Override
public void onPostExecute(JSONArray Result) {
json = Result;
}
private void Connect (String query){
httpRequest = new HTTPRequest(context);
httpRequest.execute("http://192.168.3.125:8888/data/", query);
}
}
I am new to android and am completely puzzled by AsyncTasks. I need to create a leaderboard which will pull global leaderboard scores from a server.
I have posted below the two methods that were created in the LeaderboardsFragment which are used to access and display the scores - getGlobalScores and readStream.
I am unsure of how to use these in the AsyncTask - mostly how and what parameters to pass to the AsyncTask - most of the tutorials I have been looking at do not deal with 2D arrays. Any hints would be really appreciated, I am really having trouble understanding the literature surrounding this.
package uk.ni.appidemic.whackamole;
import java.io.BufferedReader;
public class LeaderboardsFragment extends Fragment {
AssetStore AS;
private TextView TopScores;
private String[][] global_scores = new String[10][3];
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_leaderboards, container, false);
//Go and get the asset store from the activity
AS = WhackAMoleActivity.getAssetManager();
TopScores = (TextView) rootView.findViewById(R.id.leaderboards);
// Extract and display the top score text view from the preferences
displayLocalScores();
// this method is used to send a highscore to the server (name and score)
// this method may get pulled out to the gameloop as its the only place it should be used in the final game
// but this can be used for testing purposes atm (Server needs to be on)
// sendScoreGlobal("porter", 1001);
//async Get global scores from the server and display them - new thread
new AsyncOperation().execute();
...................
public void getGlobalScores() {
//gets global score in HTML format to be parsed
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
try {
URL url = new URL("http://62........./high_scores");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
readStream(con.getInputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
/gets the data and stores the global scores in a 2d array
//it then displays to screen
public void readStream(InputStream in) {
BufferedReader reader = null;
try {
StringBuilder htmlIn = new StringBuilder();
StringBuilder globalScoreBuilder = new StringBuilder();
htmlIn.append("");
reader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = reader.readLine()) != null) {
htmlIn.append(line);
}
// String to be scanned to find the pattern.
String html = htmlIn.toString();
String regexPattern = "<td align=\"left\" style=\"padding-left:10px;\">(\\d+?)</td>|<td align=\"right\" style=\"padding-right:10px;\">(\\w+?)</td>";
// Create a Pattern object
Pattern patternObject = Pattern.compile(regexPattern);
// Now create matcher object.
Matcher matcherObject = patternObject.matcher(html);
Log.d(getActivity().getResources().getString(R.string.LOG_TAG), "Trying to find regex matches");
TopScores.append("\n");
int nextFreePointer = 0;
int rowCount = 0;
while (matcherObject.find()) {
if (matcherObject.group(1) != null) {
Log.d(getActivity().getResources().getString(R.string.LOG_TAG), "Regex match : " + matcherObject.group(1));
globalScoreBuilder.append(matcherObject.group(1) + " ");
global_scores[rowCount][nextFreePointer] = matcherObject.group(1);
nextFreePointer++;
}
if (matcherObject.group(2) != null) {
Log.d(getActivity().getResources().getString(R.string.LOG_TAG), "Regex match : " + matcherObject.group(2));
globalScoreBuilder.append(matcherObject.group(2) + " ");
global_scores[rowCount][nextFreePointer] = matcherObject.group(2);
nextFreePointer++;
}
if (nextFreePointer > 2) {
nextFreePointer = 0;
rowCount++;
}
globalScoreBuilder.append("\n");
}
StringBuilder sb = new StringBuilder();
String lineSeparator = System.getProperty("line.separator");
for (String[] row : global_scores) {
sb.append(Arrays.toString(row)).append(lineSeparator);
}
String text = sb.toString();
TopScores.append("Global Top 10 Scores\n");
TopScores.append(text);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class AsyncOperation extends AsyncTask<String, Void, Void>{
protected void onPreExecute(){
}//end of onPreExecute
#Override
protected Void doInBackground(Void... values) {
}//doinBackground
protected void onProgressUpdate(Void... values){
}//onProgressUpdate
protected void onPostExecute(Void... result){
}//end of onPostExecute
}//end of AsyncOperation inner class
}//end of Leaderboards class
You should fetch your game score through a WebService class that extentds AsynTask. Below is my class that I am using in order to fetch remote data safely.
CODE:
public class WebServiceRestTask extends AsyncTask<HttpUriRequest, Void, Object> {
private static final String TAG = "WebServiceRestTask";
private AbstractHttpClient mClient;
private WeakReference<WebServiceRestCallback> mCallback;
private int ws_task;
public WebServiceRestTask(int ws_task) {
this(new DefaultHttpClient(), ws_task);
}
public WebServiceRestTask(AbstractHttpClient client, int task_number) {
mClient = client;
this.ws_task = task_number;
}
public interface WebServiceRestCallback {
public void onRequestSuccess(String response);
public void onRequestError(Exception error);
}
public void setResponseCallback(WebServiceRestCallback callback) {
mCallback = new WeakReference<WebServiceRestCallback>(callback);
}
#Override
protected Object doInBackground(HttpUriRequest... params) {
try {
HttpUriRequest request = params[0];
HttpResponse serverResponse = mClient.execute(request);
BasicResponseHandler handler = new BasicResponseHandler();
String response = handler.handleResponse(serverResponse);
return response + ws_task;
} catch (Exception e) {
Log.w(TAG, e);
return e;
}
}
#Override
protected void onPostExecute(Object result) {
if (mCallback != null && mCallback.get() != null) {
if (result instanceof String) {
mCallback.get().onRequestSuccess((String) result);
} else if (result instanceof Exception) {
mCallback.get().onRequestError((Exception) result);
} else {
mCallback.get().onRequestError(
new IOException("Unknown Error Contacting Host"));
}
}
}
}
Not at my workstation but think something like this should work.
public class AsyncOperation extends AsyncTask<String, Void, Void>{
private String[][] global_scores = new String[10][3];
protected void onPreExecute(){
// optionally show loading indicator
TopScores.append("\n");
}//end of onPreExecute
#Override
protected Void doInBackground(Void... values) {
try {
URL url = new URL("http://62........./high_scores");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
readStream(con.getInputStream());
} catch (Exception e) {
e.printStackTrace();
}
}//doinBackground
protected void onProgressUpdate(Void... values){
}//onProgressUpdate
protected void onPostExecute(Void... result){
// optionally hide loading indicator
StringBuilder sb = new StringBuilder();
String lineSeparator = System.getProperty("line.separator");
for (String[] row : global_scores) {
sb.append(Arrays.toString(row)).append(lineSeparator);
}
String text = sb.toString();
TopScores.append("Global Top 10 Scores\n");
TopScores.append(text);
}//end of onPostExecute
private void readStream(InputStream in) {
BufferedReader reader = null;
try {
StringBuilder htmlIn = new StringBuilder();
StringBuilder globalScoreBuilder = new StringBuilder();
htmlIn.append("");
reader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = reader.readLine()) != null) {
htmlIn.append(line);
}
// String to be scanned to find the pattern.
String html = htmlIn.toString();
String regexPattern = "<td align=\"left\" style=\"padding-left:10px;\">(\\d+?)</td>|<td align=\"right\" style=\"padding-right:10px;\">(\\w+?)</td>";
// Create a Pattern object
Pattern patternObject = Pattern.compile(regexPattern);
// Now create matcher object.
Matcher matcherObject = patternObject.matcher(html);
Log.d(getActivity().getResources().getString(R.string.LOG_TAG), "Trying to find regex matches");
int nextFreePointer = 0;
int rowCount = 0;
while (matcherObject.find()) {
if (matcherObject.group(1) != null) {
Log.d(getActivity().getResources().getString(R.string.LOG_TAG), "Regex match : " + matcherObject.group(1));
globalScoreBuilder.append(matcherObject.group(1) + " ");
global_scores[rowCount][nextFreePointer] = matcherObject.group(1);
nextFreePointer++;
}
if (matcherObject.group(2) != null) {
Log.d(getActivity().getResources().getString(R.string.LOG_TAG), "Regex match : " + matcherObject.group(2));
globalScoreBuilder.append(matcherObject.group(2) + " ");
global_scores[rowCount][nextFreePointer] = matcherObject.group(2);
nextFreePointer++;
}
if (nextFreePointer > 2) {
nextFreePointer = 0;
rowCount++;
}
globalScoreBuilder.append("\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}//end of AsyncOperation inner class
I've been having a lot of problems making this code work.
My main activity uses ZXing to scan a barcode, and then I want to take the result of that scan and query my API with it. I know I have to use an AsyncTask to do this, but I've never used one before and I'm having a lot of trouble with it. My goal is to query the API within the AsyncTask, and then update my upcTxt TextView element with the resulting JSON String. What am I supposed to do next in my ReadJSON code?
Here's my main activity code:
public class Barcode extends Activity implements OnClickListener {
private Button scanBtn;
private TextView formatTxt, contentTxt, upcTxt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_barcode);
scanBtn = (Button)findViewById(R.id.scan_button);
formatTxt = (TextView)findViewById(R.id.scan_format);
contentTxt = (TextView)findViewById(R.id.scan_content);
upcTxt = (TextView)findViewById(R.id.upc);
scanBtn.setOnClickListener(this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.barcode, menu);
return true;
}
public void onClick(View v){
//respond to clicks
if(v.getId()==R.id.scan_button){
//scan
IntentIntegrator scanIntegrator = new IntentIntegrator(this);
scanIntegrator.initiateScan();
}
}
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
//retrieve scan result
IntentResult scanningResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
if (scanningResult != null) {
//we have a result
String scanResult = scanningResult.getContents();
String scanFormat = scanningResult.getFormatName();
formatTxt.setText("FORMAT: " + scanFormat);
contentTxt.setText("CONTENT: " + scanResult);
new ReadJSON().execute(new String[] {scanResult});
} else {
Toast toast = Toast.makeText(getApplicationContext(), "No scan data received!", Toast.LENGTH_LONG);
toast.show();
}
}}
And here is my ReadJSON code:
public class ReadJSON extends AsyncTask<String, Void, Void> {
private String content;
private TextView upcTxt;
private String url;
#Override
protected Void doInBackground(String... scanResult) {
url = "REDACTED";
content = "";
HttpClient Client = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url + scanResult[0]);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
try {
content = Client.execute(httpget, responseHandler);
// Update upcTxt here
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
Thank you in advance.
Update: Whenever I try to run the code on my phone, I can scan the barcode just fine but then the program crashes once it tries to access the URL.
LogCat:
01-18 17:26:44.731: E/AndroidRuntime(24876): at com.peter.barcodetest.ReadJSON.doInBackground(ReadJSON.java:30)
01-18 17:26:44.731: E/AndroidRuntime(24876): at com.peter.barcodetest.ReadJSON.doInBackground(ReadJSON.java:1)
01-18 17:26:46.473: D/CrashAnrDetector(376): processName: com.peter.barcodetest
01-18 17:26:46.473: D/CrashAnrDetector(376): broadcastEvent : com.peter.barcodetest data_app_crash
01-18 17:26:46.913: D/PackageBroadcastService(26662): Received broadcast action=android.intent.action.PACKAGE_REPLACED and uri=com.peter.barcodetest
01-18 17:26:55.122: I/ActivityManager(376): Process com.peter.barcodetest (pid 24876) (adj 13) has died.
I changed your code to this:
Edited ReadJSON only
AsyncTask (edited)
public class ReadJSON extends AsyncTask<String, Integer, String> {
private String content;
private TextView upcTxt;
private String url;
private static final String TAG = "ReadJSON";
String s = "";
Context context;
ReadJSONCallBack callback;
public ReadJSONTask (Context context, ReadJSONCallBack cb) {
super();
this.callback = cb;
this.context = context;
}
#Override
protected String doInBackground(String... scanResult) {
url = "REDACTED";
HttpClient Client = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url + scanResult[0]);
try {
HttpResponse response = Client.execute(httpget);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
InputStream in = response.getEntity().getContent();
Log.d(TAG, "Got response");
InputStreamReader inputStreamReader = new InputStreamReader(in);
BufferedReader bufferedReader = new BufferedReader(
inputStreamReader);
StringBuilder stringBuilder = new StringBuilder();
String bufferedStrChunk = null;
while ((bufferedStrChunk = bufferedReader.readLine()) != null) {
stringBuilder.append(bufferedStrChunk);
}
Log.d(TAG, "Content: " + stringBuilder.toString());
return stringBuilder.toString();
// Update upcTxt here
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
protected void onPostExecute(String result) {
callback.setString(s);
}
// method for parsing JSON object
public String parseJSONObject(String output) {
try {
JSONArray jArray = new JSONArray(output);
for (int i = 0; i < jArray.length(); i++) {
JSONObject jObject = jArray.getJSONObject(i);
String id = jObject.getString("id");
String customer = jObject.getString("name");
String description = jObject.getString("description");
Long time = (Long) jObject.get("timeAsDate");
// do something
}
} catch (JSONException e) {
}
return description;
}
}
Is it possible to make AsyncTask.doInBackground synchronized - or achieve the same result in another way?
class SynchronizedTask extends AsyncTask {
#Override
protected synchronized Integer doInBackground(Object... params) {
// do something that needs to be completed
// before another doInBackground can be called
}
}
In my case, any AsyncTask.execute() can be started before a previous one has completed, but I need to execute the code in doInBackground only after the previous task has finished.
EDIT: As correctly pointed out, the synchronization works only on the same object instance.
Unfortunately, it is not possible to create an AsyncTask and call execute() more than once on the same object instance, as specified in the "Threading rules" section of the AsyncTask documentation.
The solution is to use a custom Executor to serialize the tasks, or, if you use API 11 or above, AsyncTask.executeOnExecutor(), as suggested in the comments below.
I posted an answer showing an implementation of a SerialExecutor that can be used to queue tasks that will be executed sequentially.
Ideally, I'd like to be able to use AsyncTask.executeOnExecutor() with a SERIAL_EXECUTOR, but this is only available for API level 11 or above:
new AsyncTask().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, params);
To target the Android APIs below level 11, I ended up implementing a custom class which encapsulates an ExecutorService with a thread pool size of 1. The full code is open-sourced here.
Executors.newFixedThreadPool(int nThreads) creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue. At any point, at most nThreads threads will be active processing tasks. In my case, nThreads is 1, which means tasks can be queued, but only one task will be executed at any given time.
Here is the code:
public abstract class SerialExecutor {
private final ExecutorService mExecutorService;
public SerialExecutor() {
mExecutorService = Executors.newFixedThreadPool(1);
}
public void queue(Context context, TaskParams params) {
mExecutorService.submit(new SerialTask(context, params));
}
public void stop() {
mExecutorService.shutdown();
}
public abstract void execute(TaskParams params);
public static abstract class TaskParams { }
private class SerialTask implements Runnable {
private final Context mContext;
private final TaskParams mParams;
public SerialTask(Context context, TaskParams params) {
mContext = context;
mParams = params;
}
public void run() {
execute(mParams);
Activity a = (Activity) mContext;
a.runOnUiThread(new OnPostExecute());
}
}
/**
* Used to notify the UI thread
*/
private class OnPostExecute implements Runnable {
public void run() {
}
}
}
This can be extended and used as a serial task executor in an Activity:
public class MyActivity extends Activity {
private MySerialExecutor mSerialExecutor;
#Override
public void onCreate(Bundle savedInstanceState) {
// ...
mSerialExecutor = new MySerialExecutor();
}
#Override
protected void onDestroy() {
if (mSerialExecutor != null) {
mSerialExecutor.stop();
}
super.onDestroy();
}
public void onTrigger(int param) {
mSerialExecutor.queue(this, new MySerialExecutor.MyParams(param));
}
private static class MySerialExecutor extends SerialExecutor {
public MySerialExecutor() {
super();
}
#Override
public void execute(TaskParams params) {
MyParams myParams = (MyParams) params;
// do something...
}
public static class MyParams extends TaskParams {
// ... params definition
public MyParams(int param) {
// ... params init
}
}
}
}
You may want to think about using IntentService instead. It seems like it may be a better fit for your process since it has built in features for queuing.
public class RestAsyncTask1 extends AsyncTask<String, Void, String> {
private AsyncTaskCompleteListener callback;
private Context context;
private String method;
private static final AtomicInteger PROGRESS_NUM = new AtomicInteger(0);
private static ProgressDialog PROGRESS_DIALOG;
public RestAsyncTask1(Context context, AsyncTaskCompleteListener callback, String method) {
this.callback = callback;
this.context = context;
this.method = method;
}
public static String format(String url, String... params) {
String[] encoded = new String[params.length];
for (int i = 0; i < params.length; i++) {
encoded[i] = Uri.encode(params[i]);
}
return String.format(url, (String[]) encoded);
}
#Override
protected void onPreExecute() {
int x = PROGRESS_NUM.getAndIncrement();
if (x == 0) {
String title = "M_yug";
PROGRESS_DIALOG = new ProgressDialog(context);
// PROGRESS_DIALOG.setTitle(title);
PROGRESS_DIALOG.setIndeterminate(true);
PROGRESS_DIALOG.setCancelable(false);
PROGRESS_DIALOG.setOnCancelListener(null);
PROGRESS_DIALOG.setMessage("Loading. Please wait...");
PROGRESS_DIALOG.show();
}
}
#Override
protected String doInBackground(String... params) {
String url = params[0];
String response = null;
HttpURLConnection connection = null;
if (params.length > 1) {
if (method.equals(Method.GET)) {
url = format(url, (String[]) Arrays.copyOfRange(params, 1, params.length));
} else if (params.length > 2) {
url = format(url, (String[]) Arrays.copyOfRange(params, 1, params.length - 1));
}
try {
URL call = new URL(url);
connection = (HttpURLConnection) call.openConnection();
connection.setRequestProperty("Content-Type", "application/json");
//connection.setRequestProperty("M-Yug", Utilities.VERSION);
connection.setRequestMethod(method);
connection.setDoOutput(true);
if (method.equals("POST")) {
BufferedOutputStream outputStream = new BufferedOutputStream(connection.getOutputStream());
outputStream.write(params[params.length - 1].getBytes());
outputStream.flush();
}
int status = connection.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
InputStream is = connection.getInputStream();
response = readValue(is);
} else if (status == 400) {
InputStream is = connection.getErrorStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder builder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
reader.close();
Toast.makeText(context, "" + builder.toString(), Toast.LENGTH_SHORT).show();
}
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
return response;
}
#Override
protected void onPostExecute(String s) {
int x = PROGRESS_NUM.decrementAndGet();
if (x == 0 && PROGRESS_DIALOG != null && PROGRESS_DIALOG.isShowing()) {
PROGRESS_DIALOG.dismiss();
}
if (s!=null) {
String resopnse=s.toString();
callback.onSuccess(resopnse);
} else {
Toast.makeText(context,"Server Not Responding",Toast.LENGTH_SHORT).show();
}
}
private String readValue(InputStream is) {
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
String line;
try {
br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
sb.append(line);
}
} catch (Exception e) {
}
return sb.toString();
}
enum Method {
GET, POST
}
}
AsyncTask is used to run a background thread so that you current process is not interupted .
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
where first of all your doInBackground function iscalled and the returned object will move to on post execute.
which line of code you want to run after some process you can put that in PostExecute function.
this will surely help you