I have a problem and I can't find the solution on the internet. I saw a lot of examples but no one really answered to my problem.
I have a login page and then, after checked if the both fields (login/pass) are filled, try to connect by another thread.
public class LoginActivity extends AppCompatActivity {
private EditText login = null;
private EditText password = null;
private RadioButton radioButton = null;
private Button button = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
login = (EditText)findViewById(R.id.loginEditText);
password = (EditText)findViewById(R.id.passwordEditText);
radioButton = (RadioButton)findViewById(R.id.saveRadioButton);
button = (Button)findViewById(R.id.ConnectionButton);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (login.getText().toString().equals("")
|| password.getText().toString().equals("")) {
alert(getString(R.string.alertDialoguErrorTitle), getString(R.string.UnfilledFieldLogin));
} else {
boolean haveToSave = radioButton.isChecked();
User user = User.getUser(login.getText().toString(), password.getText().toString());
try {
Intranet.login.start();
Intranet.login.join();
Intranet.login.interrupt();
Intranet.login.join();
} catch (InterruptedException e) {
alert(getString(R.string.alertDialoguErrorTitle), e.toString());
login.setText("");
password.setText("");
} finally {
if (!user._token.equals("")) {
if (haveToSave) {
// SAVE DATA
}
finish();
} else {
login.setText("");
password.setText("");
alert(getString(R.string.alertDialoguErrorTitle), getString(R.string.badLoginPassword));
}
}
}
}
});
}
public void alert(String title, String message) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(LoginActivity.this);
alertDialog.setTitle(title);
alertDialog.setMessage(message);
alertDialog.setPositiveButton("Close",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// nothing
}
});
alertDialog.show();
}
}
// The class using on the other thread
public class Intranet {
public static int responseCode = 0;
public static String responseString = "";
public static Thread login = new Thread(new Runnable() {
private OkHttpClient client = new OkHttpClient();
private String url = "https://epitech-api.herokuapp.com/login";
private User user = User.getUser();
public void run() {
try {
// Build the request
RequestBody formBody = new FormEncodingBuilder()
.add("login", user._login)
.add("password", user._password)
.build();
Request request = new Request.Builder()
.url(url)
.post(formBody)
.build();
Response responses = null;
// Reset the response code
responseCode = 0;
// Make the request
responses = client.newCall(request).execute();
if ((responseCode = responses.code()) == 200) {
// Get response
String jsonData = responses.body().string();
// Transform reponse to JSon Object
JSONObject json = new JSONObject(jsonData);
// Use the JSon Object
user._token = json.getString("token");
}
} catch (IOException e) {
responseString = e.toString();
} catch (JSONException e) {
responseString = e.toString();
}
;
}
});
}
I tried a lot of solutions with join() which wait the end of the thread. But finally, all time at the second time, when I try to connect myself, an exception comes up (The thread is already started). So how can this thread still running if it's interrupted before continuing?
Related
I am trying to trigger a piece of code on button click using View.setOnClickListener.
My code includes two OkHttp requests going to Google Places API which returns JSON files. I parse them and then place a call on a phone number extracted using the APIs.
Now, when I click on the button, the code is executed only partially. It executes the first request and returns the Place ID of the place I need. But, the phone call is not placed.
On using Logcat, we can see that the place ID is extracted, but only when I click the button once again, the complete code is executed and I see double output, i.e. the phone number extracted is logged twice.
Please help me in clearing this execution flow problem and making sure that the single click is enough to request the 2 APIs and then place the call also.
Below is the code for the onCreate method of my Activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkPerms(this);
simpleLocation = new SimpleLocation(this, true);
tv1 = findViewById(R.id.tv1);
tv2 = findViewById(R.id.tv2);
bt = findViewById(R.id.bt);
String apikey = getString(R.string.apikey);
bt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
simpleLocation.beginUpdates();
final double latitude = simpleLocation.getLatitude();
final double longitude = simpleLocation.getLongitude();
tv1.setText(String.valueOf(latitude));
tv2.setText(String.valueOf(longitude));
ExecutorService ex = Executors.newFixedThreadPool(1);
final FutureTask<String> result1 = (FutureTask<String>) ex.submit(new Callable<String>() {
public String call(){
OkHttpClient client = new OkHttpClient();
Request request1 =new Request.Builder()
.url(URLBuilder1(latitude, longitude, apikey))
.get()
.build();
try{
Response response = client.newCall(request1).execute();
JSONObject jsonObject = new JSONObject(response.body().string());
pid = jsonObject.getJSONArray("results").getJSONObject(0).getString("place_id");
} catch (IOException | JSONException e) {
e.printStackTrace();
Log.d("JSON 1", e.getLocalizedMessage());
}
return pid;
}
});
try {
PID = result1.get();
Log.d("TAG", PID);
}
catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
final FutureTask<String> result2 = (FutureTask<String>) ex.submit(new Callable<String>() {
#Override
public String call() {
try {
OkHttpClient client = new OkHttpClient();
Request request2 = new Request.Builder()
.url(URLBuilder2(apikey, pid))
.get()
.build();
Response response = client.newCall(request2).execute();
JSONObject jsonObject = new JSONObject(Objects.requireNonNull(response.body()).string());
phone = jsonObject.getJSONObject("result").getString("international_phone_number");
phone = phone.replace(" ", "");
Log.d("TAG", phone);
}
catch (IOException | JSONException e){
e.printStackTrace();
}
return phone;
}
});
try {
phone = result2.get();
Log.d("TAG", phone);
}
catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
Log.d("TAG", phone);
Intent i = new Intent(Intent.ACTION_CALL);
i.setData(Uri.parse("tel:" + phone));
}
});
}
p.s. I am a student developer who began Java for Android only 2 months ago, so any tips on code optimization or any other tips regarding bettering the code will be highly appreciated.
You should nest the two requests.
So first you should run the first request. then right after you assign the pid variable you should start the second request. Then right after you assign the phone variable you should start the phone call intent. Its simple as that. Second request should be inside the first request. Phone Call Intent should be inside the second request. I hope you'd understand.
In your code what happens is, before you receive the pid the second request is also executed. Its better if you could use Volley Library by Google
Example Code
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_about);
context = this;
checkPerms(this);
simpleLocation = new SimpleLocation(this, true);
tv1 = findViewById(R.id.tv1);
tv2 = findViewById(R.id.tv2);
bt = findViewById(R.id.bt);
String apikey = getString(R.string.apikey);
bt.setOnClickListener(new View.OnClickListener() {#Override
public void onClick(View v) {
simpleLocation.beginUpdates();
final double latitude = simpleLocation.getLatitude();
final double longitude = simpleLocation.getLongitude();
tv1.setText(String.valueOf(latitude));
tv2.setText(String.valueOf(longitude));
ExecutorService ex = Executors.newFixedThreadPool(1);
final FutureTask < String > result1 = (FutureTask < String > ) ex.submit(new Callable < String > () {
public String call() {
OkHttpClient client = new OkHttpClient();
Request request1 = new Request.Builder().url(URLBuilder1(latitude, longitude, apikey)).get().build();
try {
Response response = client.newCall(request1).execute();
JSONObject jsonObject = new JSONObject(response.body().string());
pid = jsonObject.getJSONArray("results").getJSONObject(0).getString("place_id");
final FutureTask < String > result2 = (FutureTask < String > ) ex.submit(new Callable < String > () {#Override
public String call() {
try {
OkHttpClient client = new OkHttpClient();
Request request2 = new Request.Builder().url(URLBuilder2(apikey, pid)).get().build();
Response response = client.newCall(request2).execute();
JSONObject jsonObject = new JSONObject(Objects.requireNonNull(response.body()).string());
phone = jsonObject.getJSONObject("result").getString("international_phone_number");
phone = phone.replace(" ", "");
Log.d("TAG", phone);
Intent i = new Intent(Intent.ACTION_CALL);
i.setData(Uri.parse("tel:" + phone));
}
catch(IOException | JSONException e) {
e.printStackTrace();
}
return phone;
}
});
} catch(IOException | JSONException e) {
e.printStackTrace();
Log.d("JSON 1", e.getLocalizedMessage());
}
return pid;
}
});
}
});
}
Alternatevely you can use OkHttp in async manner. For example:
ExecutorService ex = Executors.newFixedThreadPool(1);
ex.submit(new Runnable() {
public void run() {
OkHttpClient client = new OkHttpClient();
Request request1 = new Request.Builder()
.url(URLBuilder1(latitude, longitude, apikey))
.get()
.build();
client.newCall(request1).enqueue(new Callback() {
#Override
public void onFailure(#NotNull Call call, #NotNull IOException e) {
//logging
}
#Override
public void onResponse(#NotNull Call call, #NotNull Response response) throws IOException {
try {
JSONObject jsonObject = new JSONObject(response.body().string());
pid = jsonObject.getJSONArray("results").getJSONObject(0).getString("place_id");
Log.d("TAG", pid);
} catch (IOException | JSONException e) {
e.printStackTrace();
Log.d("JSON 1", e.getLocalizedMessage());
}
Request request2 = new Request.Builder()
.url(URLBuilder2(apikey, pid))
.get()
.build();
OkHttpClient client = new OkHttpClient();
client.newCall(request2).enqueue(new Callback() {
#Override
public void onFailure(#NotNull Call call, #NotNull IOException e) {
}
#Override
public void onResponse(#NotNull Call call, #NotNull Response response) throws IOException {
try {
JSONObject jsonObject = new JSONObject(Objects.requireNonNull(response.body()).string());
phone = jsonObject.getJSONObject("result").getString("international_phone_number");
phone = phone.replace(" ", "");
Log.d("TAG", phone);
Intent i = new Intent(Intent.ACTION_CALL);
i.setData(Uri.parse("tel:" + phone));
} catch (IOException | JSONException e) {
e.printStackTrace();
}
}
});
}
});
}
});
Note: I did not run the code above, just giving an example.
Instead of client.newCall(request1).execute(); which runs synchronically, you can use:
client.newCall(request1).enqueue(new Callback() {
#Override
public void onFailure(#NotNull Call call, #NotNull IOException e) {
//if request fails then this method gets executed
}
#Override
public void onResponse(#NotNull Call call, #NotNull Response response) throws IOException {
//response is coming as method parameter "response"
}
});
which is completely async.
So I have been trying to make a feature in my app where I can login and then fetch data from my database through the Django REST Framework. My logging in works as it only uses POST, but retrieving items does not work.
For some reason my AsyncTask does not get called for retrieving posts.
I have placed my AsyncTask for both activities, which are login and posts, on a separate java file only for handling Web Server stuff.
I am wondering if this is because I should put AsyncTask on each activities.
login.java
public class Login extends AppCompatActivity {
Button LoginButton;
EditText uUserName, uPassWord;
WSAdapter.SendAPIRequests AuthHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
//SetupHomeBtn = (ImageButton) findViewById(R.id.SetupHomeBtn);
LoginButton = (Button) findViewById(R.id.LoginButton);
uUserName = (EditText) findViewById(R.id.LoginUserBox);
uPassWord = (EditText) findViewById(R.id.LoginPassBox);
//AuthHelper = new WSAdapter().new SendDeviceDetails();
// Moves user to the main page after validation
LoginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// gets the username and password from the EditText
String strUserName = uUserName.getText().toString();
String strPassWord = uPassWord.getText().toString();
// API url duh
String APIUrl = "http://192.168.0.18:8000/token-auth/";
// If the user is authenticated, then transfer to the MainActivity page
if (APIAuthentication(strUserName, strPassWord, APIUrl)){
startActivity(new Intent(Login.this, Posts.class));
}
}
});
}
private boolean APIAuthentication(String un, String pw, String url){
// when it wasn't static -> AuthHelper = new WSAdapter().new SendAPIRequests();
AuthHelper = new WSAdapter.SendAPIRequests();
JSONObject postData = new JSONObject();
try {
// Attempt to input info to the Django API
postData.put("username", un);
postData.put("password", pw);
// Putting the data to be posted in the Django API
AuthHelper.execute(url, postData.toString());
return true;
} catch (JSONException e) {
e.printStackTrace();
}
return false;
}
}
posts.java
public class Posts extends AppCompatActivity {
TextView postsSect;
Button postsDoneBtn;
WSAdapter.SendAPIRequests PostsHelper;
StringBuilder postsBuffer = new StringBuilder();
#Override
protected void onResume(){
super.onResume();
PostsDetails postDetailsHelper = new PostsDetails();
postDetailsHelper.ListPosts();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_posts);
PostsDetails postDetailsHelper = new PostsDetails();
postsDoneBtn = (Button) findViewById(R.id.PostsDoneButton);
postDetailsHelper.callPostDetails("192.168.0.18:8000/api");
postDetailsHelper.ListPosts();
postDetailsHelper.postDetailsCalled('n');
postsDoneBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(Posts.this, MainActivity.class));
}
});
}
public class PostsDetails {
//String post_title, post_content;
ArrayList<Integer> post_id = new ArrayList<Integer>();
ArrayList<String> post_title = new ArrayList<String>();
ArrayList<String> post_content = new ArrayList<String>();
boolean isPDCalled;
// sets if Post details are called
boolean postDetailsCalled(char called) {
if (called == 'y'){
return true;
}
return false;
}
// checks if postsDetails functions are called for AsyncTask
boolean getIsPDCalled(){
return isPDCalled;
}
// calls the execute for AsyncTask
private void callPostDetails(String theurl){
PostsHelper = new WSAdapter.SendAPIRequests();
// sets if post details are called
postDetailsCalled('y');
// executes AsyncTask
PostsHelper.execute(theurl);
}
// sets values for the posts arrays
public void setPost(int p_id, String p_title, String p_content) {
post_id.add(p_id);
post_title.add(p_title);
post_content.add(p_content);
}
// Lists the posts from the database
public void ListPosts() {
/////////// add functionality if a post was deleted and was clicked
postsSect = (TextView) findViewById(R.id.PostsSection);
postsSect.setText(post_title.get(post_title.size()) + "\n");
for (int i = post_id.size() - 1; i > 0; i--)
{
postsSect.append(post_title.get(i));
}
}
}
}
WSAdapter.java
// I forgot what WS stands for, but this class serves as an adapter for JSON and Online stuff
// I think it stands for With-Server Adapter
public class WSAdapter extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
static public class SendAPIRequests extends AsyncTask<String, String, String> {
// Add a pre-execute thing
#Override
protected String doInBackground(String... params) {
Log.e("TAG", params[0]);
Log.e("TAG", params[1]);
String data = "";
HttpURLConnection httpURLConnection = null;
try {
// Sets up connection to the URL (params[0] from .execute in "login")
httpURLConnection = (HttpURLConnection) new URL(params[0]).openConnection();
// Sets the request method for the URL
httpURLConnection.setRequestMethod("POST");
// Tells the URL that I am sending a POST request body
httpURLConnection.setDoOutput(true);
// To write primitive Java data types to an output stream in a portable way
DataOutputStream wr = new DataOutputStream(httpURLConnection.getOutputStream());
// Writes out a byte to the underlying output stream of the data posted from .execute function
wr.writeBytes("postData=" + params[1]);
// Flushes the postData to the output stream
wr.flush();
wr.close();
// Representing the input stream
InputStream in = httpURLConnection.getInputStream();
// Preparing input stream bytes to be decoded to charset
InputStreamReader inputStreamReader = new InputStreamReader(in);
StringBuilder dataBuffer = new StringBuilder();
// Translates input stream bytes to charset
int inputStreamData = inputStreamReader.read();
while (inputStreamData != -1) {
char current = (char) inputStreamData;
inputStreamData = inputStreamReader.read();
// concatenates data characters from input stream
dataBuffer.append(current);
}
data = dataBuffer.toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
// Disconnects socket after using
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
}
Log.e("TAG", data);
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// expecting a response code fro my server upon receiving the POST data
Log.e("TAG", result);
Posts.PostsDetails postsHelper = new Posts().new PostsDetails();
// For posts
try {
if (postsHelper.getIsPDCalled()){
JSONObject pJObj = new JSONObject(result);
JSONArray pJObjArray = pJObj.getJSONArray("posts");
for (int i = 0; i < pJObjArray.length(); i++) {
JSONObject pJObj_data = pJObjArray.getJSONObject(i);
postsHelper.setPost(pJObj_data.getInt("id"), "post_title", "post_content");
}
}
} catch (JSONException e) {
//Toast.makeText(JSonActivity.this, e.toString(), Toast.LENGTH_LONG).show();
Log.d("Json","Exception = "+e.toString());
}
}
}
}
Yes, you can and should put the network calls functions in a separate java file for better readability and test-coverage.
Apart from that, i would suggest to use Retrofit as your HTTP client. It helps you to manage all the dirty things like headers and converters etc, so you can put all your effort on your logic and implementing your callback actions.
This question already has answers here:
How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?
(17 answers)
Closed 5 years ago.
How to catch moment when AsyncTask is finished?
I have ProfileUpdate class which extends AsyncTask, and from another activity I calling this method and after I need update my data. How to know that asynctask finished? My asynctask method in another class and not in activity class!!!
this is my onRefresh method in the activity:
#Override
public void onRefresh() {
if (!AlertView.isInternetAvailable(getContext())) {
swipeLayout.setRefreshing(false);
Toast.makeText(getContext(), Messages.CONNECTION_ERROR + ": " + Messages.NO_INTERNET, Toast.LENGTH_SHORT).show();
} else {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
new UpdateProfile(getActivity(), swipeLayout, sharedPreferences.getString(Constants.TOKEN, ""), user.getIin()).execute(Urls.GET_USER);
}
});
profileDefaults();
}
}
and here my AsyncTask method:
public class UpdateProfile extends AsyncTask <String, Void, String> {
private Activity activity;
private SwipeRefreshLayout swipeRefreshLayout;
private String token;
private String userIin;
private SharedPreferences sharedPreferences;
public UpdateProfile(Activity activity, SwipeRefreshLayout swipeRefreshLayout, String token, String userIin) {
this.activity = activity;
this.swipeRefreshLayout = swipeRefreshLayout;
this.token = token;
this.userIin = userIin;
sharedPreferences = this.activity.getSharedPreferences(Constants.PROJECT, Context.MODE_PRIVATE);
}
#Override
protected String doInBackground(String... params) {
URL url = null;
try {
url = new URL(params[0]);
try {
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody body = new FormBody.Builder()
.add("iin", userIin)
.build();
Request request = new Request.Builder()
.url(url)
.addHeader(Constants.AUTH_TOKEN, token)
.post(body)
.build();
Response responses = null;
try {
responses = okHttpClient.newCall(request).execute();
} catch (Exception e) {
AlertView.showAlertView(activity, Messages.CONNECTION_ERROR, Messages.NO_INTERNET, Messages.OK);
}
assert responses != null;
return responses.body().string();
} catch (Exception e) {
AlertView.showAlertView(activity, Messages.CONNECTION_ERROR, Messages.NO_INTERNET, Messages.OK);
}
} catch (Exception e) {
AlertView.showAlertView(activity, Messages.CONNECTION_ERROR, Messages.NO_INTERNET, Messages.OK);
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
try {
JSONObject jsonObject = new JSONObject(s);
int code = Integer.valueOf(jsonObject.getString(Constants.CODE));
if (code == Codes.OK) {
Toast.makeText(activity, "Данные обновлены", Toast.LENGTH_SHORT).show();
String userHeader = jsonObject.getString("user");
JSONObject userInfo = new JSONObject(userHeader);
String mobilePhone = userInfo.getString(SingletonConstants.MOBILE_PHONE);
Boolean isActive = userInfo.getBoolean(SingletonConstants.IS_ACTIVE);
Boolean signedAgreement = userInfo.getBoolean(SingletonConstants.SIGNED_AGREEMENT);
Boolean esfEntered = userInfo.getBoolean(SingletonConstants.ESF_ENTERED);
String address = userInfo.getString(SingletonConstants.ADDRESS);
String iin = userInfo.getString(SingletonConstants.IIN);
String certExpDate = userInfo.getString(SingletonConstants.CERT_EXP_DATE);
String firstName = userInfo.getString(SingletonConstants.FIRST_NAME);
String middleName = userInfo.getString(SingletonConstants.MIDDLE_NAME);
String workPhone = userInfo.getString(SingletonConstants.WORK_PHONE);
String secondName = userInfo.getString(SingletonConstants.SECOND_NAME);
String avatarUrl = userInfo.getString(SingletonConstants.AVATAR_URL);;
String secondEmail = userInfo.getString(SingletonConstants.SECOND_EMAIL);
String email = userInfo.getString(SingletonConstants.EMAIL);
User newUser = new User(mobilePhone, isActive, signedAgreement, esfEntered, address, iin, certExpDate, firstName, middleName, workPhone, secondName, avatarUrl, secondEmail, email);
Gson gson = new Gson ();
String userGson = gson.toJson (newUser);
sharedPreferences.edit().putString(SingletonConstants.USER, userGson).apply();
swipeRefreshLayout.setRefreshing(false);
} else {
AlertView.showAlertView(activity, Messages.ERROR, jsonObject.getString(Constants.MESSAGE), Messages.OK);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
How I can call profileDefaults()? It's into my activity. And I need to call it after onPostExecute!
A cleaner way to do it is to use interfaces as listeners.
Create this interface:
public interface OnAsyncFinished{
void onAsyncFinished(Object o);
}
Add the interface as a parameter in your AsyncTaskClass constructor:
private OnAsyncFinished onAsyncFinished;
public UpdateProfile(..., OnAsyncFinished onAsyncFinished) {
...
this.onAsyncFinished = onAsyncFinished;
}
...
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
onAsyncFinished.onAsyncFinished(s); //This will notifiy the method on main activity, and you can now resume the work there
...
}
Implement the interface in your main activity:
public MainActivity extends Activity implements OnAsyncFinished {
#Override
public void onAsyncFinished(Object o) {
//This will get called after onPostExecute, do what u want with the object you got from onPostExecute, json or string in ur example
profileDefaults(); //call ur function
}
}
EDIT:
When creating the async task in your main activity pass this in the constructor likeso:
#Override
public void run() {
new UpdateProfile(..., this).execute(Urls.GET_USER);
}
I'm writing an Android application which will occasionally need to download a json string of around 1MB and containing around 1000 elements, and parse each of these into an SQLite database, which I use to populate a ListActivity.
Even though the downloading and parsing isn't something that needs to be done on every interaction with the app (only on first run or when the user chooses to refresh the data), I'm still concerned that the parsing part is taking too long, at around two to three minutes - it seems like an eternity in phone app terms!
I am using this code... :-
public class CustomerAsyncTask extends AsyncTask<String, Integer, String> {
private Context context;
private String url_string;
private String usedMethod;
private String identifier;
List<NameValuePair> parameter;
private boolean runInBackground;
AsynTaskListener listener;
private Bitmap bm = null;
public ProgressDialog pDialog;
public String entityUtil;
int index = 0;
public static int retry = 0;
private String jsonString = "";
private String DialogString = "";
// use for AsyncTask web services-----------------
public CustomerAsyncTask(Context ctx, String url, String usedMethod,
String identifier, boolean runInBackground, String DialogString,
List<NameValuePair> parameter, AsynTaskListener callack) {
this.context = ctx;
this.url_string = url;
this.usedMethod = usedMethod;
this.identifier = identifier;
this.parameter = parameter;
this.runInBackground = runInBackground;
this.listener = callack;
this.DialogString = DialogString;
}
public CustomerAsyncTask(Context ctx, String url, String usedMethod,
String identifier, boolean runInBackground,
List<NameValuePair> parameter, AsynTaskListener callack, Bitmap bm) {
this.context = ctx;
this.url_string = url;
this.usedMethod = usedMethod;
this.identifier = identifier;
this.parameter = parameter;
this.runInBackground = runInBackground;
this.listener = callack;
this.bm = bm;
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
if (runInBackground)
initProgressDialog(DialogString);
}
#Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
}
#SuppressWarnings("deprecation")
#Override
protected String doInBackground(String... params) {
HttpParams httpParameters = new BasicHttpParams();
int timeoutConnection = 10000; // mili second
HttpConnectionParams.setConnectionTimeout(httpParameters,
timeoutConnection);
int timeoutSocket = 10000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
try {
HttpResponse response = null;
if (usedMethod.equals(GlobalConst.POST)) {
HttpPost httppost = new HttpPost(this.url_string);
httppost.setHeader("Content-Type",
"application/x-www-form-urlencoded");
// Customer Login MObile
if (identifier.equals("Customer_Login")) {
if (params.length > 0) {
parameter = new ArrayList<NameValuePair>();
parameter.add(new BasicNameValuePair("cus_mob",
params[0]));
}
httppost.setEntity(new UrlEncodedFormEntity(parameter));
// Customer Verify Code
} else if (identifier.equals("Customer_mob_verify")) {
if (params.length > 0) {
parameter = new ArrayList<NameValuePair>();
parameter.add(new BasicNameValuePair("cus_verify",
params[0]));
parameter.add(new BasicNameValuePair("cus_mobile",
params[1]));
}
httppost.setEntity(new UrlEncodedFormEntity(parameter));
} else if (identifier.equals("Dashboard")) {
if (params.length > 0) {
parameter = new ArrayList<NameValuePair>();
parameter.add(new BasicNameValuePair("cus_id",
params[0]));
}
httppost.setEntity(new UrlEncodedFormEntity(parameter));
}
response = (HttpResponse) httpClient.execute(httppost);
} else if (usedMethod.equals(GlobalConst.GET)) {
HttpGet httpput = new HttpGet(this.url_string);
httpput.setHeader("Content-Type",
"application/x-www-form-urlencoded");
response = (HttpResponse) httpClient.execute(httpput);
}
// Buffer Reader------------------------
InputStream inputStream = null;
String result = null;
try {
HttpEntity entity1 = response.getEntity();
inputStream = entity1.getContent();
BufferedReader reader = new BufferedReader(
new InputStreamReader(inputStream, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
result = sb.toString();
} catch (Exception e) {
} finally {
try {
if (inputStream != null)
inputStream.close();
} catch (Exception squish) {
}
}
jsonString = result;
} catch (ClientProtocolException e) {
e.printStackTrace();
return AsyncResultConst.CONNEERROR;
} catch (IOException e) {
e.printStackTrace();
return AsyncResultConst.CONNEERROR;
} catch (Exception e1) {
e1.printStackTrace();
return AsyncResultConst.EXCEPTION;
} finally {
httpClient.getConnectionManager().shutdown();
}
return AsyncResultConst.SUCCESS;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
if (runInBackground)
pDialog.dismiss();
if (result.equals(AsyncResultConst.SUCCESS)) {
listener.onRecieveResult(identifier, jsonString);
} else if (result.equals(AsyncResultConst.PARSINGERROR)) {
// showAlertMessage(context, "Error", "Parsing Error", null);
listener.onRecieveException(identifier, result);
} else {
if (retry < 0) {
retry++;
new CustomerAsyncTask(context, url_string, usedMethod,
identifier, runInBackground, DialogString, parameter,
listener).execute("");
} else {
// showAlertMessage(context, "Error", "Connection Error", null);
listener.onRecieveException(identifier, result);
}
}
super.onPostExecute(result);
}
private void initProgressDialog(String loadingText) {
pDialog = new ProgressDialog(this.context);
pDialog.setMessage(loadingText);
pDialog.setCancelable(false);
pDialog.show();
}
}
Don't use Async-task in such case, use native java thread here.
new Thread(new Runnable() {
public void run() {
// Do your work .....
}
}).start();
When need to update UI. Yes! Android won't allow you to do that. so... solution is: USE Handler for that :)
Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
// Do Update your UI
}
});
Use AsyncTask for:
Simple network operations which do not require downloading a lot of
data Disk-bound tasks that might take more than a few milliseconds
Use Java threads for:
Network operations which involve moderate to large amounts of data (either uploading or downloading)
High-CPU tasks which need to be run in the background
Any task where you want to control the CPU usage relative to the GUI thread
You could use Google's GSON as well.
Try to use Jackson Library to manage your JSON. It is really efficient. You can find it here : http://mvnrepository.com/artifact/org.codehaus.jackson/jackson-jaxrs
I am using it for a 400KB file is less than 1 second.
If you want a tuto this one looks good http://www.mkyong.com/java/how-to-convert-java-object-to-from-json-jackson/
This is how is read JSON into my listview in my app. The result is processed to my app in an average of 3 seconds on Wi-Fi and 5 seconds on 3G:
public class CoreTeamFragment extends ListFragment {
ArrayList> membersList;
private String url_all_leaders = //URL goes here
private ProgressDialog pDialog;
JSONParser jParser = new JSONParser();
// JSON Node names
private static final String CONNECTION_STATUS = "success";
private static final String TABLE_TEAM = "CoreTeam";
private static final String pid = "pid";
private static final String COL_NAME = "CoreTeam_Name";
private static final String COL_DESC = "CoreTeam_Desc";
private static final String COL_PIC = "CoreTeam_Picture";
JSONArray CoreTeam = null;
public static final String ARG_SECTION_NUMBER = "section_number";
public CoreTeamFragment() {
}
public void onStart() {
super.onStart();
membersList = new ArrayList<HashMap<String, String>>();
new LoadAllMembers().execute();
// selecting single ListView item
ListView lv = getListView();
// Lauching the Event details screen on selecting a single event
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// getting values from selected ListItem
String ID = ((TextView) view.findViewById(R.id.leader_id))
.getText().toString();
Intent intent = new Intent(view.getContext(),
CoreTeamDetails.class);
intent.putExtra(pid, ID);
view.getContext().startActivity(intent);
}
});
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_coreteam,
container, false);
return rootView;
}
class LoadAllMembers extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(getActivity());
pDialog.setMessage("Just a moment...");
pDialog.setIndeterminate(true);
pDialog.setCancelable(true);
pDialog.show();
}
protected String doInBackground(String... args) {
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
// getting JSON string from URL
JSONObject json = jParser.makeHttpRequest(url_all_leaders,
"GET", params);
try {
// Checking for SUCCESS TAG
int success = json.getInt(CONNECTION_STATUS);
if (success == 1) {
// products found
// Getting Array of Products
CoreTeam = json.getJSONArray(TABLE_TEAM);
// looping through All Contacts
for (int i = 0; i < CoreTeam.length(); i++) {
JSONObject ct = CoreTeam.getJSONObject(i);
// Storing each json item in variable
String id = ct.getString(pid);
String name = ct.getString(COL_NAME);
String desc = ct.getString(COL_DESC);
String pic = ct.getString(COL_PIC);
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(pid, id);
map.put(COL_NAME, name);
map.put(COL_DESC, desc);
map.put(COL_PIC, pic);
// adding HashList to ArrayList
membersList.add(map);
}
} else {
// Options are not available or server is down.
// Dismiss the loading dialog and display an alert
// onPostExecute
pDialog.dismiss();
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all products
pDialog.dismiss();
// updating UI from Background Thread
getActivity().runOnUiThread(new Runnable() {
public void run() {
ListAdapter adapter = new SimpleAdapter(
getActivity(),
membersList,
R.layout.coreteam_item,
new String[] { pid, COL_NAME, COL_DESC, COL_PIC },
new int[] { R.id.leader_id, R.id.leaderName,
R.id.photo });
setListAdapter(adapter);
}
});
}
}
}
Use Volley or Retrofit lib.
Those lib are increasing the speed.
Volley:
JsonObjectRequest channels = new JsonObjectRequest(Method.POST,
Constants.getaccountstatement + Constants.key, statement_object,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject arg0) {
}, new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError e) {
Toast.makeText(context, "Error", Toast.LENGTH_SHORT).show();
}
I am having a problem with my setOnClickListener. I can not figure out what the code is i need for it. What i am trying to do is once the item is clicked on in the list view it opens up a new activity. in my code the list view is in the MainActivity. and i want it to open up the Homework activity. So my question is, can anybody help me figure out what i need to put in for it to work correctly and open up Homework.java? when it opens up Homework.java it would show the item clicked in the list view as the header. then nothing in the body.
MainActivity.class:
public class VideoListTask extends AsyncTask<Void, Void, Void>{
ProgressDialog dialog;
protected void onPreExecute (Void result) {
dialog.getProgress();
super.onPostExecute(result);
}
#Override
protected Void doInBackground(Void... params)
{
HttpClient client = new DefaultHttpClient();
//HttpGet getRequest = new HttpGet(feedUrl);
Date now = new Date();
HttpGet getRequest = new HttpGet(canvasUrl + "courses? include[]=term&state=available");
getRequest.setHeader("Authorization","Bearer " + canvasApiKey); //uses your key to access your data
try
{
HttpResponse response = client.execute(getRequest);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if(statusCode != 200)
{
return null;
}
InputStream jsonStream = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(jsonStream));
StringBuilder builder = new StringBuilder();
String line;
while((line = reader.readLine())!=null)
{
builder.append(line);
}
String jsonData = builder.toString();
//JSONObject json = new JSONObject(jsonData);
//JSONObject data = json.getJSONObject("data");
//JSONArray items = data.getJSONArray("items");
JSONArray courses = new JSONArray(jsonData);
//for(int i =0; i<items.length(); i++)
//{
// JSONObject video = items.getJSONObject(i);
// videoArrayList.add(video.getString("title"));
//}
for(int i = 0; i<courses.length(); i++)
{
JSONObject course = courses.getJSONObject(i);
JSONObject term = course.getJSONObject("term");
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
try {
Date enddate = format.parse(term.getString("end_at"));
Date startdate = format.parse(term.getString("start_at"));
if (now.after(startdate) && now.before(enddate))
{
videoArrayList.add(course.getString("name"));
}
} catch (Exception e) {
//videoArrayList.add(course.getString("name"));//include if you want undated courses
}
}
}
catch (ClientProtocolException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
THIS IS WHERE I NEED TO PUT THE ONCLICK LISTENER IN.
}
If Homework.java is your second activity you can set a click listener in this way
Main Activity
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
....
ListView myListView = (ListView) findViewById(R.id.myListView);
myListView.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> adapter, View v, int position,
long arg3)
{
startActivity(new Intent(MainActivity.this, Homework.class));
}
});
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
try{
Class<?> ourClass=Class.forName("com.example.projname.Homework");
Intent ourIntent= new Intent(MainActivity.this,ourClass);
ourIntent.putExtra("matrix", m);
startActivity(ourIntent);
}catch(ClassNotFoundException e){
e.printStackTrace();
}
});
The data you pass using putExtra will be available to you in the Homeactivity.java