Android: Getting null value in islatedProcess - java

I have an App that run an isolated process.
The problem is, i'm getting correctly UserID from another Service but when I execute getUsersNotfs(url) I'm getting null on String s onPostExecute: 05-14 11:23:39.806 17705-17705/com.example.diabetes:offline_notifications I/System.out: null
But if I run this without an isolated process the String is correct and I get the correct results ([{"RecordID":"1","UserID":"1","RecordDate":"2018-05-08 00:00:00"}])
This is my code:
Passing UserID:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
uid = intent.getStringExtra("UserID");
startTimer();
return START_STICKY;
}
public void getUserNotfs(final String urlWebService) {
class GetJSON extends AsyncTask<Void, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
System.out.println(s);
}
#Override
protected String doInBackground(Void... voids) {
try {
URL url = new URL(urlWebService);
System.out.println(url);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
StringBuilder sb = new StringBuilder();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(con.getInputStream()));
String json;
while ((json = bufferedReader.readLine()) != null) {
sb.append(json + "\n");
}
return sb.toString().trim();
} catch (Exception e) {
return null;
}
}
}
GetJSON getJSON = new GetJSON();
getJSON.execute();
}
Thanks

Isolated process will have it's own instance hence you are not getting the value.
Try to use some persistent storage like SQLite,keep the value there and access from your isolated process.
You will get that.
As mentioned in https://developer.android.com/guide/topics/manifest/service-element#isolated
Your service is isolated from the rest of the system and has no permissions of its own. That means it dont have INTERNET permission.Hence can't fetch data.

Related

Passing value from onResponse to onPostExecute keep turning to null

I'm connecting to API with the async task. I need to pass two values from the API to the app, in onResponse I have logged the values and got them right. But in onPostExecute one of them keep turning into null
I have already tried to check different values from API and logs to see if the value that I'm looking for is there or if the connection is valid, everything went alright until it hits the onPostExecute where I'm getting only one value
public class ChooseLocationTask extends AsyncTask<String, Void, Void> {
OkHttpClient client = new OkHttpClient.Builder()
//default timeout for not annotated requests
.readTimeout(15000, TimeUnit.MILLISECONDS)
.connectTimeout(15000, TimeUnit.MILLISECONDS)
.writeTimeout(15000, TimeUnit.MILLISECONDS)
.build();
Request request;
private TextView location;
private TextView value;
String state;
Number probability;
String probablityString;
public ChooseLocationTask(TextView location, int selected, TextView value){
this.location = location;
this.value = value;
}
#Override
protected void onProgressUpdate(Void...values){
super.onProgressUpdate(values);
}
#Override
protected void onPreExecute(){
super.onPreExecute();
}
#Override
protected Void doInBackground(String... urls) {
request = new Request.Builder().url(urls[0]).build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
Log.d("CallMsg", String.valueOf(call));
}
#Override
public void onResponse(Call call, Response response) throws IOException {
Log.d("Response", String.valueOf(response));
try {
JSONObject jsonObject = new JSONObject(response.body().string());
JSONObject weather = jsonObject.getJSONObject("weather");
JSONObject location = weather.getJSONObject("location");
state = location.getString("state");
JSONObject percentage = jsonObject.getJSONObject("probability");
JSONObject calculated = percentage.getJSONObject("highest");
probability = calculated.getInt("value");
probablityString = probability.toString();
Log.d("percentage", probability.toString());
Log.d("String",probablityString);
Log.d("location",state);
} catch (JSONException e){
e.printStackTrace();
}
}
});
return null;
}
#Override
protected void onPostExecute(Void voids){
if(isCancelled()){
voids= null;
} else {
location.setText(state);
value.setText("your chance to see Northern lights today is" + probablityString);
Log.d("value", "onPostExecute: " + probablityString);
}
Log.d("post", "onPostExecute: " + probability);
}
}
Basically, all I need is advice on how to get this value, I feel like maybe I made mistake when converting it into a string, but in logs, in onResponse it shows quite alright, so I don't know. Thank you for all the advice
Retrofit has two techniques for performing requests, one synchronous (execute()) and another asynchronous (enqueue()). You are using the asynchronous technique, and as a result, when you go to execute your AsyncTask, your doInBackground() method immediately calls enqueue(), completes, and calls onPostExecute() before your request has completed.
You have two options. First, you can keep your current AsyncTask, but replace enqueue() for execute(). This will look a little like:
public class ChooseLocationTask extends AsyncTask<String, Void, Void> {
private final OkHttpClient client = new OkHttpClient.Builder()
//default timeout for not annotated requests
.readTimeout(15000, TimeUnit.MILLISECONDS)
.connectTimeout(15000, TimeUnit.MILLISECONDS)
.writeTimeout(15000, TimeUnit.MILLISECONDS)
.build();
private final Request request;
private final TextView location;
private final TextView value;
String state;
Number probability;
String probablityString;
public ChooseLocationTask(TextView location, int selected, TextView value){
this.location = location;
this.value = value;
}
#Override
protected Void doInBackground(String... urls) {
request = new Request.Builder().url(urls[0]).build();
try {
final Response<?> response = client.newCall(request).execute();
if(response.isSuccessful()) {
final JSONObject jsonObject = new JsonObject(response.body().string());
//etc...
}
} catch (IOException e) {
//...
}
//I'd recommend you return values as well, rather than assigning them to
//instance variables
return null;
}
#Override
protected void onPostExecute(Void voids){
if(isCancelled()){
voids= null;
} else {
location.setText(state);
value.setText("your chance to see Northern lights today is" + probablityString);
Log.d("value", "onPostExecute: " + probablityString);
}
Log.d("post", "onPostExecute: " + probability);
}
Or, you can get rid of your AsyncTask entirely, and just call enqueue()

Managing multiple Async tasks in android

Hey everyone so I am just starting a part two for online training app and trying to adapt my async task to get movie reviews from the movie db. Having a totally different async task just for that seems like there should be a better way. Here is the current async task implementation that only gets the movie data.
The question is how do I add another async task to this in order to retrive the movie reviews as well from this url /movie/{id}/videos.
public FetchMovieData(Context context, GridView grid, boolean sortType, ITaskCompleteListener listener) {
mContext = context;
this.mMoviesGrid = grid;
this.mSortByMostPopular = sortType;
this.mTaskCompleteListener = listener;
}
#Override
protected Void doInBackground(String... params) {
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
try {
URL url;
if(mSortByMostPopular)
url = new URL(mContext.getString(R.string.picasso_url_popular_movies));
else
url = new URL(mContext.getString(R.string.picasso_url_highest_rated));
// Create the request to OpenWeatherMap, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
mMovieJsonStr = null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
mMovieJsonStr = null;
}
mMovieJsonStr = buffer.toString();
} catch (IOException e) {
Log.e("PlaceholderFragment", "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attempting
// to parse it.
mMovieJsonStr = null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("PlaceholderFragment", "Error closing stream", e);
}
}
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if(mMovieJsonStr != null)
Constants.mMovies = MovieDataParser.getMovieData(mMovieJsonStr);
mTaskCompleteListener.onTaskCompleted(); //Task completed alert UI that we have our data
}
So some one had suggested using Retrofit instead of having multiple async tasks. This seems like a good idea but I am having a lot of trouble understanding how it is supposed to work. Currently I have a WebService class an interface and am trying to use it to retrieve both movies and am going to add reviews then trailers. The issue is if I set the base url as "http://api.themoviedb.org" I get url must start with "/" in logcat.
Current code:
public class WebService {
public List<Movie> getMovies() {
RestAdapter retrofit = new RestAdapter.Builder()
.setEndpoint("http://api.themoviedb.org")
.build();
MovieDBService service = retrofit.create(MovieDBService.class);
return service.listMovies("movies");
}
}
public interface MovieDBService {
#GET("/3/discover/{switchterm}sort_by=popularity.desc&api_key=d273a1a1fb9390dab9 7ac0032b12366a")
List listMovies(#Path("switchterm") String switchterm);
}
//In code getting movies
WebService service = new WebService();
List movies = service.getMovies();
I think you have a lots of possibilities for doing this.You can follow this approach: add a second call to another AsyncTask when the first is finish, and pass to it a list of strings with the video ids:
public class FetchMovieData extends AsyncTask<Void, Void, Void> {
protected Boolean doInBackground() {
try {
String movieJSONString = getJSONMovies();
String[] ids = parseIdsFromJSON(movieJSONString);
if(ids.lenth != 0) {
FetchMovieReviews moviesReviewsAsyncTask = new FetchMovieReviews();
moviesReviewsAsyncTask.execute(ids);
} else {
return false;
}
return true;
} catch (Exception e) {
return false;
}
}
protected String getJSONMovies() {
//with the code you post, return the json string
}
protected String[] parseIdsFromJSON(String JSON) {
//parse the json and get the ids and return
//return {"1","2","3"}
}
}
public class FetchMovieReviews extends AsyncTask<String[], Void, Void> {
protected Void doInBackground(String[]... params) {
for(String id : params[0]) {
//call the web service and pass the id
}
return null;
}
}
You can put all the functionality for manage the calls to the web services in a MoviesRESTCalls class, and for manage the json in a MoviesJSONParser class or something like that, and the code is going to be much more clear.
So what I ended up with was this using the the Retrofit library for the web service. Thanks for the help everyone and let me know your thoughts.
public Context mContext;
private MovieJSON mMovieData;
private ReviewJSON mMovieReviews;
private VideoJSON mMovieVideos;
public boolean mSortByMostPopular;
ITaskCompleteListener mTaskCompleteListener;
public FetchMovieData(Context context, boolean sortType, ITaskCompleteListener listener) {
mContext = context;
this.mSortByMostPopular = sortType;
this.mTaskCompleteListener = listener;
}
public void getMovies() {
new FetchMovies().execute();
}
public void getReviews() {
new FetchReviews().execute();
}
public void getVideos() {
new FetchTrailers().execute();
}
private class FetchMovies extends AsyncTask<String, Void, Void > {
#Override
protected Void doInBackground(String... params) {
WebService service = new WebService();
//TODO Re-Implement sorting
mMovieData = service.getMovies();
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if(mMovieData != null)
Constants.mMovies = MovieDataParser.getMovieData(mMovieData);
mTaskCompleteListener.onTaskCompleted(); //Task completed alert UI that we have our data
}
}
private class FetchReviews extends AsyncTask<String, Void, Void > {
#Override
protected Void doInBackground(String... params) {
WebService service = new WebService();
mMovieReviews = service.getReviews();
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if(mMovieReviews != null)
Constants.mReviews = MovieDataParser.getReviewData(mMovieReviews);
mTaskCompleteListener.onTaskCompleted(); //Task completed alert UI that we have our data
}
}
private class FetchTrailers extends AsyncTask<String, Void, Void > {
#Override
protected Void doInBackground(String... params) {
WebService service = new WebService();
mMovieVideos = service.getVideos();
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if(mMovieVideos != null)
Constants.mTrailers = MovieDataParser.getVideoData(mMovieVideos);
mTaskCompleteListener.onTaskCompleted(); //Task completed alert UI that we have our data
}
}
//web service
public class WebService {
RestAdapter mRetrofit;
MovieDBService mService;
public WebService() {
mRetrofit = new RestAdapter.Builder()
.setEndpoint("http://api.themoviedb.org")
.build();
mService = mRetrofit.create(MovieDBService.class);
}
public MovieJSON getMovies() {
return mService.listMovies("");
}
public ReviewJSON getReviews() {
return mService.listReviews("76341");
}
public VideoJSON getVideos() {
return mService.listVideos("76341");
}
}

Asynctask class to rerun itself again?

Hello i have a class which runs my getQus class(via asynctask)
The problem right now is that im trying to set it in such a way that if
my return result is null, to rerun the getQus again with updated variables, i.e to increase my topic& lvl till i get a valid result.
This is my flow of my system.
1st class( set topic&lvl)-> Pass topic&lvl over to getQus -> getQus returns result via onPostExecute(delegate).
1st Class Code
public void GenerateQus(){
//run code to get new qus
x.setLvl(lvl);
x.setTopic(topic);
System.out.println("GENERATEQUS:"+ lvl +" , "+topic);
new getQus(CAT.this).execute(x);
}
getQus Class
protected Question doInBackground(Level... params) {
int r = params[0].getLvl();
int z = params[0].getTopic();
System.out.println("getQlvl:" + r);
System.out.println("getQtopic:" + z);
String range = String.valueOf(r);
String topic = String.valueOf(z);
// TODO Auto-generated method stub
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("range",range));
nameValuePairs.add(new BasicNameValuePair("topic",topic));
int q_id = 0;
String result=null;
String q_qus =" ";
String result2 = " ";
Question q = new Question();
InputStream is = null;
try {
Globals g = Globals.getInstance();
String ip = g.getip();
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://"+ip+"/fyp/qus.php");
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
}catch(Exception e){
Log.e("log_tag", "Error in http connection "+e.toString());
}
//convert response to string
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result2=sb.toString();
System.out.println("TEDASD: "+result2);
if(result2.equals("[]")){
//to rerun again
}
What should i do so that getQus will re-call itself again? Thanks in advance!
If I understood your problem correctly, you just want to rerun logic in doInBackground. So, why don't you just do something like this?
protected Question doInBackground(Level... params) {
Question q;
while((q = doTheStuff(params))==null){
updateParams(params);
}
return q;
}
private Question doTheStuff(Level.. params){
//your logic here
}
private void updateParams(Level.. params){
//update params here
}
If you can update x only in the main thread, you can reexecute the task in onPostExecute:
public class SomeActivity extends Activity {
private X x = new X();
#Override protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new AsyncTask<X, String, Long>() {
#Override protected Long doInBackground(final X... params) {
// do something here
return null;
}
#Override protected void onPostExecute(final Long result) {
if (result == null) {
// update args and restart task
x.setFoo("a");
x.setBar("b");
execute(x);
}
}
}.execute(x);
}
private class X {
String foo;
String bar;
public void setFoo(final String foo) {
this.foo = foo;
}
public void setBar(final String bar) {
this.bar = bar;
}
}
}
In onPostExecute() method you will get the result. so if your result is null there the start the AysncTask there itselt.

Android AsynchTask data return to Activity

I have a MainActivity class from which I am calling an instance of my JsonObj class.
JsonObj extends AsynchTask. It's pasted below:
public class JsonObj extends AsyncTask<String, Void, JSONObject>{
int tid;
String term;
#Override
protected JSONObject doInBackground(String... url) {
// TODO Auto-generated method stub
DefaultHttpClient httpclient = new DefaultHttpClient(new BasicHttpParams());
HttpPost httppost = new HttpPost(url[0]);
JSONObject jsonObject = null;
// Depends on your web service
httppost.setHeader("Content-type", "application/json");
InputStream inputStream = null;
String result = null;
try {
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
inputStream = entity.getContent();
// json is UTF-8 by default
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();
// Log.e("JSON-Test [RESULT]: ", result);
jsonObject = new JSONObject(result);
} catch (Exception e) {
Log.e("JSON-Test [exception]: ", e.toString());
}
finally {
try{if(inputStream != null)inputStream.close();}catch(Exception squish){}
}
return jsonObject;
}
#Override
protected void onPostExecute(JSONObject result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
}
What I am trying to achieve is an AsyncTask class which I can call from any activity that will fetch and return JSON from my server.
My problem is my AsyncTask class successfully fetches my JSON but I am struggling to pass it back to my Activity.
I know the OnPostExecute function returns data on completion of my AsyncTask but all my attempts to access the data in my Activity class are not working.
I'm using new JsonObj().execute("http://myserver/json"); to call my JsonObj class.
How do I call OnpostExecute to directly access data my AsynchTask fetches from my server OR what is a better solution to this problem?
Create an Interface that has a method called something like "onServiceFinished" which your activities that make this call implement. Then when you call your AsyncTask, pass it (this) and in your onPostExectue, call FinishedListener.onServiceFinished(var1, var2) or whatever data your passing.
Code Example: This example uses an AsyncTask to retrieve a message from the server, and when that is finished, pass back that message to the class that requested it
Interface:
public interface ServiceHandler {
public abstract void onServiceFinished(JSONObject jsonObject);
}
Activity:
public class YourActivity extends Activity implements ServiceHandler {
#Override
public void onCreate(Bundle savedInstanceState) {
//Activity stuff
new JsonObj(this).execute("http://myserver/json");
}
#Override
public void onServiceFinished(JSONObject jsonObject) {
// Do something with the message
}
}
Asynctask:
public class JsonObj extends AsyncTask<String, Void, JSONObject> {
ServiceHandler handler;
public ChatAsync(ServiceHandler serviceHandler) {
handler = serviceHandler;
}
#Override
protected JSONObject doInBackground(String...params) {
// fetch messages from service and parse JSON
}
#Override
protected void onPostExecute(JSONObject json) {
handler.onServiceFinished(json);
}
}
The basic model is there, you'll have to modify it to fit what you're doing! Hope this helps
If you doing all network operation in a separate class and you want the result on the calling Activity class.
Create a method onTaskComplete(JsonObject result) on the calling Activity class.
public void onTaskComplete(JsonObject result) {
//Do You Operation
}
And now you need to call this method on OnPostExecute()
public class JsonObj extends AsyncTask<String, Void, JSONObject>{
Activity _context;
public JsonObj(Activity _context) {
this._context = _context;
}
#Override
protected void onPostExecute(JSONObject result) {
super.onPostExecute(result);
this._context.onTaskComplete(result);
}
}
At last call the AsyncTask
new JsonObj(this).execute("YOUR URL");
The best way to do this is with a Callback. With this pattern, you create an interface that you implement in your Activity. You then set a method in this interface callback to be run in your onPostExecute() method. For example, this basic AsyncTask will call the callback function when complete:
public class JsonObj extends AsyncTask<Void, Void, JSONObject> {
private OnSuccessListener listener;
private String url;
public JsonObj(String url, OnSuccessListener listener) {
this.url = url;
this.listener = listener;
}
#Override
protected JSONObject doInBackground(Void... params) {
//handle url getter. returning the JSONObject here will send it to the onPostExecute method.
}
#Override
protected void onPostExecute(JSONObject json) {
if (listener != null)
listener.onSuccess(json);
}
public interface OnSuccessListener {
public void onSuccess(JSONObject json);
}
}
Then to use this properly, just do this in your Activity:
new JsonObj("http://myserver/json", new OnSuccessListener() {
#Override
public void onSuccess(JSONObject json) {
//TODO: handle new JSONObject.
}
}).execute();
If you want a simpler, already coded solution, consider the droidQuery library that I wrote. Apart from simplifying animations and common UI tasks, it can simplify this sort of network call immensely. The above code can be compressed down to this in your Activity:
$.ajax(new AjaxOptions().url("http://myserver/json")
.type("POST")
.dataType("JSON")
.headers(new Headers().content_type("application/json"))
.success(new Function() {
#Override
public void invoke($ d, Object... args) {
JSONObject json = (JSONObject) args[0];
//TODO: handle json
}
});

Android, can I put AsyncTask in a separate class and have a callback?

I'm just learning about AsyncTask and want to use it as a separate class, rather then a subclass.
For example,
class inetloader extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String response = "";
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(urls[0]);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
return response;
}
#Override
protected void onPostExecute(String result) {
Log.e("xx",result);
// how do I pass this result back to the thread, that created me?
}
}
and the main(ui) thread:
inetloader il = new inetloader();
il.execute("http://www.google.com");
//il.onResult()
//{
///do something...
//}
Thanks!
Use a interface. Something like:
interface CallBackListener{
public void callback();
}
Then do this in your UI thread:
inetloader il = new inetloader();
li.setListener(this);
il.execute("http://www.google.com");
In inetloader, add:
CallBackListener mListener;
public void setListener(CallBackListener listener){
mListener = listener;
}
then In postExecute(), do:
mListener.callback();
you can pass the activity instance to constructor and call activity function from there...
Like use interface :
public interface ResultUpdatable {
public void setResult(Object obj);
}
Implement this in the Activity and pass in the constructor of Async task and update the result from onPostExecute using setResult function.
inetloader il = new inetloader();
il.execute("http://www.google.com");
String result = il.get();//put it in try-catch
^^^^^^^^
here you get result which is in onPostExecute(String result)

Categories

Resources