My Android application needs to do an initial http request on app start to fetch a config json file from a RESTful service. This request is done by Volley
As soon as the application gets the data, the MainActivity starts. I also defined some deeplinks, to open a WebView in my application with a given URI. The deeplinks have to be handled by the SplashActivity as the config needs to be loaded first by Volley. I don't know if this is the right way to handle this.
Maybe it would be an option to request the config in the Application class, so that the config is always available, no matter which Activity starts first?
This is the correct way.
In your Splash activity you should handle the incoming intent with your deeplinks, fire up your Volley request and only then you should move on with your logic.
BTW, in the meanwhile, you should show the user some loader/progress and handle failures of course.
If you are making an asynchronous call in the Application class, you can make the request with a callback and show the required activity.
public interface ConfigListener {
public void onConfigReceived(List<ofSomething> list, boolean error, String message);
}
private void requestConfig(){
final DownloadUsingVolley downloader = new DownloadUsingVolley(getActivity());
downloader.retrieveData(new ConfigListener() {
#Override
public void onConfigReceived(List<ofSomething> list, boolean error, String message) {
//Show your required activity here
}
});
}
private void retrieveData(String url, final ConfigListener configListener){
final JsonObjectRequest request = new JsonObjectRequest(url, null, new Response.Listener<JSONObject>(){
#Override
public void onResponse(JSONObject response) {
try {
//parse
configListener.onConfigReceived(result,false,null);
}catch (JSONException e){
configListener.onConfigReceived(0,true,e.getMessage());
}
}
},new Response.ErrorListener(){
#Override
public void onErrorResponse(VolleyError volleyError) {
configListener.onConfigReceived(0,true,volleyError.getMessage());
}
});
//adding request into the queue
ApplicationClass.getInstance().addToRequestQueue(request,"aTag");
}
Related
I am working on chat application and using ejabberd saas edition as xmpp server for it. I am using smack library ver-4.2.3. To keep connection alive I am using ping manager. Here is the code I am using:
ReconnectionManager.getInstanceFor(AppController.mXmpptcpConnection).enableAutomaticReconnection();
ServerPingWithAlarmManager.onCreate(context);
ServerPingWithAlarmManager.getInstanceFor(AppController.mXmpptcpConnection).setEnabled(true);
ReconnectionManager.setEnabledPerDefault(true);
//int i = 1;
// PingManager.setDefaultPingInterval(i);
PingManager.getInstanceFor(AppController.mXmpptcpConnection).setPingInterval(300);
I am using sticky-service also for connection, but when I keep my application open (ideal-state) for 15-20 mins then the connection is lost, so I am using ping manger to resolve this issue.
Is there any other better way of doing it or ping manager is the only option?
Insted of pinging chat server constantly, you better to use ConnectionListener() in smack library. You need to use something like this:
XMPPTCPConnection connection;
// initialize your connection
// handle the connection
connection.addConnectionListener(new ConnectionListener() {
#Override
public void connected(XMPPConnection connection) {
}
#Override
public void authenticated(XMPPConnection connection, boolean resumed) {
}
#Override
public void connectionClosed() {
// when the connection is closed, try to reconnect to the server.
}
#Override
public void connectionClosedOnError(Exception e) {
// when the connection is closed, try to reconnect to the server.
}
#Override
public void reconnectionSuccessful() {
}
#Override
public void reconnectingIn(int seconds) {
}
#Override
public void reconnectionFailed(Exception e) {
// do something here, did you want to reconnect or send the error message?
}
});
Best way to keep the alive connection with XMPP server you should reconnect after every network change.
Like this:
public class NetworkStateChangeReceiver extends BroadcastReceiver {
private Context context;
private static NetworkStateChangeListener mListener;
#Override
public void onReceive(Context context, Intent intent) {
this.context = context;
try {
if (!ApplicationHelper.isInternetOn(context)) {
if (mListener != null) {
mListener.OnInternetStateOff();
}
return;
} else {
XMPPTCPConnection xmpptcpConnection = XmppConnectionHelper.getConnection();
if(!StringHelper.isNullOrEmpty(new SessionManager(context).getAuthenticationToken())) {
Intent XmppConnectionServicesIntent = new Intent(context, XmppConnectionServices.class);
context.stopService(XmppConnectionServicesIntent);
context.startService(XmppConnectionServicesIntent);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
//to initialize NetworkStateChangeListener because null pointer exception occurred
public static void setNetworkStateChangeListener(NetworkStateChangeListener listener) {
mListener = listener;
}
}
Yes, There is. Few points before the solution
Make your service STICKY, with a foreground notification as it would be necessary to work on or after Build.VERSION_CODES.O
This sticky service, you should start on every boot, via BOOT_COMPLETED intent action and starting this foreground service from receiver.
Yes, Now it is always there, Now you can always go for checking your connection
You can use google-volley for making connections and even you can communicate using it.
There is no good documentation on it, But i like it much, as it works flawlessly once added the dependency successfully.
Adding this dependency will take time as i said no good documentation..
For communication :
StringRequest stringRequest = new StringRequest(Request.Method.POST, "https://oniony-leg.000webhostapp.com/user_validation.php",
new Response.Listener<String>()
{
#Override
public void onResponse(String response)
{
serverKeyResponse = response;
// get full table entries from below toast and writedb LICENSETABLE
//Toast.makeText(getActivity(),response,Toast.LENGTH_LONG).show();
showKeyResponse();
// Log.d("XXXXXX XXXXX", "\n SUCCESS : "+serverKeyResponse);
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error)
{
serverKeyResponse = error.toString();
// show below toast in alert dialog and it happens on slow internet try again after few minutes
// on ok exit app
// Toast.makeText(getActivity(),error.toString(),Toast.LENGTH_LONG).show();
showKeyResponse();
//Log.d("YYYYYY YYYYYY", "\n FAILURE : "+serverKeyResponse);
}
})
{
#Override
protected Map<String,String> getParams()
{
Map<String,String> params = new HashMap<String, String>();
params.put("INPUT",LicenseKey.getText().toString());
params.put("USER", MainActivity.deviceid);
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
requestQueue.add(stringRequest);
You just have to reply ECHO "SUCCESS" from server using a php ( or whatever server side language you like ). In response check for SUCCESS presence, any any other cases.., Use other KEYWORDS YOU LIKE. You can handle Server response errors too. Even you can communicate from android in request - response handshake. But you have to implement few handshake on your own.
I Hope, It helps...
Use the ReconnectionManager class as described here.
ReconnectionManager manager = ReconnectionManager.getInstanceFor(connection);
manager.enableAutomaticReconnection();
It will automatically re-connect when necessary.
I use Retrofit library to handle JSON response from my WCF web-service.
RestService.getRestService().search("tools", new Callback<SearchResult>() {
#Override
public void success(SearchResult searchResult, Response response) {
if( searchResult == null) return;
textView.setText(searchResult.toString());
} // end of success(
#Override
public void failure(RetrofitError error) {
showToast(R.string.internet_sikintisi);
}
});
I noticed that i get error if i leave the fragment or activity where i called this function from. Because I set text in textView where the activity or fragment is not already exists.
I modified the code to be like this:
RestService.getRestService().search("tools", new Callback<SearchResult>() {
#Override
public void success(SearchResult searchResult, Response response) {
if( searchResult == null) return;
try{
textView.setText(searchResult.toString());
} catch(Exception e) {}
} // end of success(
#Override
public void failure(RetrofitError error) {
try{
showToast(R.string.internet_sikintisi);
} catch(Exception e) {}
}
});
Basically, the problem solved, the app is not crashing every time the user gets in and out immediately. Still there might be a better solution for this problem.
I checked and Retrofit DOES NOT have cancel request feature!
You need to added checks success and failure methods the same way you would when using an asynctask check if the context still exist or make a isActive field that you set on onResume/onPause of the activity or fragment.
It is possible to cancel Retrofit requests in Retrofit 2(beta is available now.)
call.cancel();// as simple as that
I'm trying to use Volley to execute multiple HTTP request where each one of them relies on the result of the previous one, what is the best option as a design?
1-Firing the next request in the onResponse callback of the previous request?
2-Writing some coordinator class that have callbacks that get called in the onResponse method of a request and fires the next request
skeleton code for the second option
coodrinator = new Coordinator();
JsonObjectRequest firstRequest = new JSONObjectRequest(Request.Method.GET,firstURL),new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
//handle the responsee
coordinator.onFirstRequestRecieved();
}
},
errorListener);
private void doSecondRequest(){
JsonObjectRequest secondRequest = new JSONObjectRequest(Request.Method.GET,secondURL),new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
//handle the responsee
coordinator.onSecondRequestRecieved();
}
},
errorListener);
}
private class Coordinator{
public void onFirstReequestRecieved(){
doSecondRequest();
}
public void onSecondRequestRecieved(){
//do Something
}
}
If first request response parameters are needed for making second request and so on then you can go for synchronous way. That can be achieved by making second request in onResponse on First request can there is no good or bad practise for it.
The thing is volley is asynchronous and request what is added in the queue execute without depending on other request and we are going to make it synchronous request and it can be achieved by many ways seeing your requirement.
I've searched all over but haven't found an answer to this.
In my Android application, the user can use the app offline, and some events generate http GET requests to my server. I am using Volley, and when the user is online the requests work properly, but offline they fail immediately and are removed from the request queue.
I wanted Volley to store these requests, and try again when the server is accessible, or at least keep trying. Is this behaviour possible?
Here's how I'm doing things:
StringRequest request = new StringRequest(Request.Method.GET, url, listener, listener);
request.setRetryPolicy(new DefaultRetryPolicy(8000, 2, 1.5f));
postToDefaultQueue(request);
private void postToDefaultQueue (StringRequest request) {
if (sQueue == null) {
sQueue = Volley.newRequestQueue(mContext.get());
}
sQueue.add(request);
}
Thanks so much, any help appreciated
Edit
So I managed to make the request go back to the queue after it fails. The code is below:
private class DummyListener implements Response.Listener<String>, Response.ErrorListener {
String mUrl;
public DummyListener (String url){
mUrl = url;
}
#Override
public void onErrorResponse(final VolleyError error) {
new Timer().schedule(new TimerTask() {
#Override
public void run() {
Log.v(DummyListener.class.getSimpleName(), "ErrorResponse", error);
offlineStringGetRequest(mUrl);
}
}, 5000);
}
#Override
public void onResponse(String response) {
Log.d(DummyListener.class.getSimpleName(), "Response: " + response);
}
}
The problem that remains is that if I kill the app, the queue gets destroyed, and the request is never made.
Edit2
Noticed some people liked this question. I ended up using Path (https://github.com/path/android-priority-jobqueue) with some modifications for the job. It worked perfectly. Just wish Volley had a native way for doing this
Since I found no way to do this with Volley, I ended up using Path
And it worked wonders
I've seen answer to both of these questions, however, when I tried to put them together, I couldn't make it work. The problem itself is pretty simple: I want to get a string from one site and use it in a post request. That means I can only make the post request after I've finished parsing the GET request. The main ideas I'm using are these ones:
How to return response header field to main method using Google Volley for HTTP GET request in Android / Java?
Can I do a synchronous request with volley?
However the synchronous request is blocked and doesn't go on, and the first one is Async.
I believe this to be a simple thing to do, but still, I haven't be able to do it...
Thanks for any help!
Why not do something like this:
// send first request
requestQueue.add(firstRequest, null, new Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
// ** code to parse response **
// send second request
requestQueue.add(secondRequest, null, new Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
// ** code to parse response **
}
}, new ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// ** code to handle errors **
}
}));
}
}, new ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// ** code to handle errors **
}
}));