i have made an app, which sending/receiving lat long to/from server continuously.also retrieving and showing information from server.i have used asynctask for network call. but one problem when phonecall came and apps in background my apps lost its connection;like not show any server information nor send lat long to server in right destination. how to solve this? like if i would use volley then singleton class may help to solve this problem is there any solution for asynctask?
this is my asynctask:
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class
GetPostAsyncTask extends AsyncTask<String, Void, String> {
public AsyncResult asyncResult;
// HttpURLConnection httpURLConnection;
// private static String responseStr = "";
// private static String responseStrLogin = "";
ProgressDialog progressDialog;
private final String baseUrl = UserInfo.getBaseUrl();
Context context;
GetPostAsyncTask(Context context,AsyncResult asyncResult) {
this.context=context;
this.asyncResult= asyncResult;
}
#Override
protected void onPreExecute() {
//Toast.makeText(context,"Loading..",Toast.LENGTH_SHORT).show();
progressDialog=new ProgressDialog(context);
progressDialog.show();
}
#Override
protected String doInBackground(String... args) {
try {
// setting the URL
URL url = new URL(baseUrl+args[1]);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.addRequestProperty("User-Agent", "RealTimeApps/1.0");
// setting the method type
httpURLConnection.setRequestMethod(args[0]);
// httpURLConnection.setChunkedStreamingMode(0);
httpURLConnection.setDoInput(true);
httpURLConnection.setDoOutput(true);
OutputStream outputStream = httpURLConnection.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
Log.v("Url",args[2]);
// setting the identification key name with query params
bufferedWriter.write(args[2]);
bufferedWriter.flush();
bufferedWriter.close();
Log.v("GetPostA", url.toString());
httpURLConnection.connect();
int getPostStatus = httpURLConnection.getResponseCode();
Log.v("GetPostSts", String.valueOf(getPostStatus));
String line = "";
String res = "";
// if(getPostStatus == 200){
// prepare the output buffer
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
while ((line = bufferedReader.readLine()) != null) {
res += line;
}
inputStream.close();
// }
httpURLConnection.disconnect();
return res.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
Log.v("GetPostCatchMal",e.toString());
} catch (IOException e) {
e.printStackTrace();
Log.v("GetPostCatchIOE", e.toString());
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
progressDialog.dismiss();
if(result!=null) {
asyncResult.asyncResult(result);
}
}
}
i am very new in android and unable to find the solution of this problem.any help please. TIA
You need to listen to incoming calls using an IncomingCallReceiver (user-defined : code given below) and suspend/stop your Asynctask when you receive a call, and resume/restart it when the call ends.
For stop-restart case:
In your Asynctask you can make it loop on a sharedpreference flag variable for continuous behavior and set the flag to false when call comes. When call ends, you can initiate the Asynctask again.
Code for IncomingCallReceiver:
public class IncomingCallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// 2
this.context = context;
try{
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (TelephonyManager.EXTRA_STATE_RINGING.equals(state))
{
//Call incoming
}
else if(TelephonyManager.EXTRA_STATE_OFFHOOK.equals(state))
{
//Call picked up
}
else if(TelephonyManager.EXTRA_STATE_IDLE.equals(state))
{
//Call ends
}
}
catch(Exception e)
{
e.printStackTrace();
}
Incoming call receiver tutorial: http://www.theappguruz.com/blog/detecting-incoming-phone-calls-in-android
Shared preferences tutorial : https://www.tutorialspoint.com/android/android_shared_preferences.htm
Asynctask tutorial: https://developer.android.com/reference/android/os/AsyncTask.html
Singleton class tutorial: https://sourcemaking.com/design_patterns/singleton
You can run that code in a Service. The service can run in the background (even when app is paused/stopped) - which means that even when a phone call comes in (which puts your activity in paused state) your code should run without interruptions.
Make sure you read more about the lifecycle of the Service to implement what you're trying to do properly.
EDIT:
To run the AsyncTask within the Service, create an instance of that task when creating the Service (see Service lifecycle) and run the task there.
When you try to start a Service that is already running, it won't create another instance but rather will return an instance of the running Service, however it will call onStartCommand again.
You can bind the service to your activity(s) to communicate with it.
1.
<service
android:name=".AsyncTaskInServiceService">
</service>
2.
public class ServiceReciever extends BroadcastReceiver {
#Override
public void onReceive(final Context context, Intent intent) {
TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(new PhoneStateListener(){
#Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
System.out.println("incomingNumber : " + incomingNumber);
Toast.makeText(context,incomingNumber,Toast.LENGTH_LONG).show();
Asynchtask().execute();//Write the code here
}
},PhoneStateListener.LISTEN_CALL_STATE);
}
Related
Helloo, I know there is a lot of posts abnout this but ITS SO confusing i'v read alot of them but i can't manage to solve a simple probleme. All i want is to get a Class from my main activity.kt when i do
val QuizzList = Network().execute(); (in main activity.kt)
I want QuizzList to be my class, not a Async task blabla.
What do i need to do in here to make this task returns a QuizCollection (its a custom class)?
package com.example.myapplication;
import android.os.AsyncTask;
import android.os.Build;
import androidx.annotation.RequiresApi;
import com.google.gson.Gson;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class Network extends AsyncTask<String, Integer, Object> {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
// constructor
public Network() {
}
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
protected QuizCollection doInBackground(String... params) {
try {
// On doit utiliser cet adresse URL, le 127.0.0.1 ne marche pas a cause du serveur qui
// Roule deja sur l'adresse.
//Get the content from the server
URL url = new URL("http://10.0.2.2:8080/api/quizz");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestProperty("Content-Type", "application/json");
con.setRequestMethod("GET");
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer content = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
}
Gson gson = new Gson();
JSONArray jsonArray = new JSONArray(content.toString());
System.out.println("Le content : "+content.toString());
QuizCollection quizz = new QuizCollection();
for (int i=0; i<jsonArray.length();i++){
System.out.println(jsonArray.get(0).toString());
Quiz quiz = gson.fromJson(jsonArray.getJSONObject(i).toString(), Quiz.class);
System.out.println("Titre "+quiz.Title);
quizz.addQuiz(quiz);
}
System.out.println("ca fonctionne?"+quizz.QuizArray.get(0).Title);
in.close();
return quizz;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Object page)
{
//onPostExecute
}
}
You should use callback
public interface OnTaskCompleted{
void onTaskCompleted(QuizCollection collection);
}
In your Activity:
//do whatever you want with collection which is the object returned from AsyncTask
Network(OnTaskCompleted { collection -> collection.toString() }).execute()
And your AsyncTask:
public class YourTask extends AsyncTask<Object,Object,QuizCollection >{
private OnTaskCompleted listener;
public YourTask(OnTaskCompleted listener){
this.listener=listener;
}
// required methods
protected QuizCollection doInBackground(String... params) {
return new QuizCollection();
}
protected void onPostExecute(QuizCollection collection){
// your stuff
listener.onTaskCompleted(collection);
}
}
I had to do this
protected void onPostExecute(QuizCollection result)
{
//onPostExecute
super.onPostExecute(result);
}
And do a .get() after calling execute
I'm writing a basic application in Android, the application will be connected to MySql server by quest in PHP, in Android Internet connection have to make in diffrent thread, so I create class which implements Runnable interface.
package com.company.opax.loginmysql;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
/**
* Created by opax on 30.08.2015.
*/
public class HttpPostMethod implements Runnable{
private String fileInHost;
private ArrayList<PostParameters> postParameterses;
private StringBuffer postResult;
public HttpPostMethod(String fileInHost, ArrayList<PostParameters> postParameterses){
this.fileInHost = fileInHost;
this.postParameterses = new ArrayList<PostParameters>(postParameterses);
}
public String getResult() {
return postResult.toString();
}
#Override
public void run() {
try {
String urlParameters = generateParameters();
URLConnection conn = initializeUrlConnection();
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
writer.write(urlParameters);
writer.flush();
String line;
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
while ((line = reader.readLine()) != null) {
postResult.append(line);
}
writer.close();
reader.close();
} catch (IOException e) {
Log.e("Exception", this.getClass().getName() + " name: " + e.toString());
}
}
private URLConnection initializeUrlConnection() throws MalformedURLException {
URL url = new URL(fileInHost);
URLConnection conn;
try {
conn = url.openConnection();
conn.setDoOutput(true);
}catch(IOException e){
throw new MalformedURLException();
}
return conn;
}
private String generateParameters(){
StringBuffer finishPostQuery = new StringBuffer();
for(PostParameters p : postParameterses){
finishPostQuery.append(p.getNameParam());
finishPostQuery.append("=");
finishPostQuery.append(p.getValueParam());
finishPostQuery.append("&");
}
if(!finishPostQuery.toString().equals("login=seba&password=pass&"))
throw new AssertionError("blad generatora zapytania: " + finishPostQuery);
return finishPostQuery.toString();
}
}
and login class:
public class Login {
private User user;
private final String paramLogin = "login";
private final String paramPass = "password";
public Login(User user){
this.user = user;
}
public boolean tryLogin(){
try{
ArrayList<PostParameters> postParameterses = new ArrayList<>();
postParameterses.add(new PostParameters(paramLogin, user.getUserName()));
postParameterses.add(new PostParameters(paramPass, user.getUserPass()));
HttpPostMethod httpPostMethod = new HttpPostMethod("http://blaba.php", postParameterses);
httpPostMethod.run();
Log.i("bla", httpPostMethod.getResult());
} catch (Exception e) {
Log.i("Exception", e.toString());
}
return false;
}
}
I'm trying to connect in other thread, but I still have an error: 'android.os.NetworkOnMainThreadException'
I would be grateful for the all suggestion what I do wrong.
Instead of:
httpPostMethod.run();
do:
new Thread(httpPostMethod).start();
In case your login call failed for some reasons (timeout, wrong login), you should report that somehow to user - this is what AsyncTask class is for. It allows you to run background code in doInBackkground, and after network operation ends - in onPostExecute you can execute UI related stuff - like show errors/results.
I suggest you two things.
First use AsyncTask instead of pure java threads.
But the main advice is to use a library that make http requests.
I like to use Retrofit, it may handle all request and thread part for you, but there are others.
I'm having some difficulties with my app. I created a class with functions to handle HTTP POST by starting a thread, the issue is that I cannot send data outside the thread!!! The class has a variable and I want to set value to that variable when the thread is running, please help.
Here is the code:
package com.mypackage;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import org.json.JSONObject;
import org.json.JSONException;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Handler;
import android.util.Log;
public class HandleJSON {
private String urlString = null;
private int errorcode ;
public int getErrorcode(){return errorcode;}
public volatile boolean parsingComplete = true;
public HandleJSON(String url){
//saving the URL
this.urlString = url;
}
#SuppressLint("NewApi")
public void readAndParseJSON(String in) {
try {
parsingComplete = false;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void fetchJSON(){
Thread thread = new Thread(new Runnable(){
#Override
public void run() {
try {
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.connect();
//receiving message from server
InputStream stream = conn.getInputStream();
String data = convertStreamToString(stream);
// JSON thing
try{
JSONObject obj = new JSONObject(data);
//THIS IS THE ISSUE, I'm setting here the errorcode which should set the superclass variable "errorcode" so I can use "getErrorCode" to retrieve the code, but it seems like the thread does not respond after thread starts;
errorcode = obj.getInt("error_code");
}
catch(JSONException e) {
Log.e("Catch error", e.toString());
}
readAndParseJSON(data);
stream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
}
static String convertStreamToString(java.io.InputStream is) {
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
}
If I understand correctly, you want to get data between a non-main thread and elsewhere. In which case you may want to create another class that has a public static variable. This is such that everyone permitted by the modifier in question (private, protected, public) can access the same content. Be careful as, if poorly managed, your code may function differently or not all on systems with execution speeds other than yours.
In such case, an anonymous daemon thread is a little tricky.
You can define a concrete class extending Thread, define data structures in it and provide the interface to access your data structures. Such as here below.
class MyThread extends Thread {
private JSONObject obj;
public void run() {
// Your parsing code goes here
// Such as obj = xxxxxx;
}
public JSONObject getData() {
return obj;
}
}
Of course, you should consider the concurrent risks when manipulating inner data structures.
The issue solved, I used AsyncTask instead and passed the variables to onPostExecute(String) which done the trick.
I try to get xml from server in async task, but my doInBackground method returns me NULL. Where is my mistake? And how I can send result to UI?
Here is all classes
I have this code for getting xml from server:
package classes;
import android.os.AsyncTask;
import android.util.Log;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
import java.net.URL;
/**
* Created by Mikhail on 28.03.2015.
*/
public class GetXMLFromServer {
InputStreamReader reader;
public GetXMLFromServer(){
//reader = null;
}
public InputStreamReader getReaderWithXML(String url){
GetXMlTask task = new GetXMlTask();
task.execute(url);
return reader;
}
public void setReader(InputStreamReader newReader){
this.reader = newReader;
}
class GetXMlTask extends AsyncTask<String, Integer, InputStreamReader>{
#Override
protected InputStreamReader doInBackground(String... params) {
InputStreamReader iStream = null;
try {
iStream = new InputStreamReader(getUrlData(params[0]));
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return iStream;
}
#Override
protected void onPostExecute(InputStreamReader inputStreamReader) {
super.onPostExecute(inputStreamReader);
setReader(inputStreamReader);
}
public InputStream getUrlData(String urlString) throws URISyntaxException, IOException {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet method = new HttpGet(String.valueOf(new URL(urlString)));
HttpResponse res = client.execute(method);
StatusLine status = res.getStatusLine();
if (status.getStatusCode() != 200) {
Log.d("APP", "HTTP error.Invalid server status code: " + res.getStatusLine());
}
return res.getEntity().getContent();
}
}
}
You have a good example how to use async task here.
Please check it!
The returning is in onPostExecute method.
To send the result to UI use OnPostExecute do call a static method of your UI class.
protected void onPostExecute(Long result) {
YourUIFragmentORActivity.showResult(result);
showDialog("Downloaded " + result + " bytes");
}
I am parsing the Json and display on list view using gson library. When I insert my input stream I am getting null values. Can you please tell where I am wrong I will give you steps
I downloaded 2.3 Gson library. Then I make getter and setter
------------------
package com.firstgroup.webservice;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import com.firstgroup.dto.Holder;
import com.firstgroup.webservicecallback.WebserviceCallBack;
import com.google.gson.Gson;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
public class RequestTask extends AsyncTask<String, String, String>{
private WebserviceCallBack callBack;
private ProgressDialog progressDialog;
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
progressDialog= new ProgressDialog((Context) callBack);
super.onPreExecute();
progressDialog.setTitle("Please Wait...");
progressDialog.setMessage("Webservice Call...");
progressDialog.setCancelable(true);
progressDialog.show();
}
#Override
protected String doInBackground(String... uri) {
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response;
String responseString = null;
try {
response = httpclient.execute(new HttpGet(uri[0]));
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpStatus.SC_OK){
// I am getting correct result here ...
Reader reader = new InputStreamReader(response.getEntity().getContent());
Gson gson = new Gson();
Holder response1 = gson.fromJson(reader, Holder.class);
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
responseString = out.toString();
} else{
//Closes the connection.
response.getEntity().getContent().close();
throw new IOException(statusLine.getReasonPhrase());
}
} catch (ClientProtocolException e) {
//TODO Handle problems..\
progressDialog.hide();
} catch (IOException e) {
//TODO Handle problems..
progressDialog.hide();
}
return responseString;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
//Do anything with response..
if(callBack!=null){
callBack.getWebserviceResponse(result);
}
progressDialog.hide();
}
public void setObserver(WebserviceCallBack callback){
callBack=callback;
}
}
callback on main activity:
#Override
public void getWebserviceResponse(String response) {
// TODO Auto-generated method stub
Log.d("response", response);
//can I used this code ?
// I want to used gson in main activity?
Reader reader = new InputStreamReader(response.getEntity().getContent());
Gson gson = new Gson();
Holder response1 = gson.fromJson(reader, Holder.class);
}
}
Add a class:
public class Holder {
List<deparaturedaseboarddto> data;
}
And change your below code:
deparaturedaseboarddto response1 = gson.fromJson(reader, deparaturedaseboarddto.class);
to:
Holder response1 = gson.fromJson(reader, Holder.class);
Reason: Your json text value has a root object named as data and it has a list of deparaturedaseboarddto. You are trying to deserialize this json value to a deparaturedaseboarddto instance but it is an object which has a list of deparaturedaseboarddto.
Also (not relevant to your error);
1) Class names starts with capital letters, and field names are camel case at Java.
2) You don't have to use #SerializedName if the java class's field name
is same with the json value's field name.
3) Below mapping is probably prevent an error because there are no fields at json value named as Result. #SerializedName("Result") may be removed or replaced with #SerializedName("alertsId")
#SerializedName("Result")
int alertsId;
4) Also may want to replace below code:
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
responseString = out.toString();
with:
responseString = gson.toJson(response1);
Edit for the second question at the comment:
If you want to use retrieve Holder instance from AsyncTask, make below edits.
Change this:
public class RequestTask extends AsyncTask<String, String, String>
with this:
public class RequestTask extends AsyncTask<String, String, Holder>
and:
protected String doInBackground(String... uri)
with this:
protected Holder doInBackground(String... uri)
and this:
protected void onPostExecute(String result)
with this:
protected void onPostExecute(Holder result)