I am doing the following which perfectly works
//else proceed with the checks
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(
Request.Method.GET,
checkauthurl,
null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(String response) {
//do stuff here
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// do stuff here
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String> ();
TokenService tokenservice = new TokenService(ctx);
String accesstoken = tokenservice.getToken(ApiHelper.ACCESS_TOKEN_SHARED_PREF);
headers.put("Authorization", "Bearer " + accesstoken);
return headers;
}
};
// Access the RequestQueue through your singleton class.
ApiSingleton strngle = new ApiSingleton(ctx);
strngle.addToRequestQueue(jsonObjectRequest);
For every request, I have to add the request header. How can I set request headers directly in the singleton.
This is my singleton
private static ApiSingleton mInstance;
private RequestQueue mRequestQueue;
public static Context mCtx;
private ImageLoader mImageLoader;
public ApiSingleton(Context context) {
mCtx = context;
mRequestQueue = getRequestQueue();
//do stuff
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
// getApplicationContext() is key, it keeps you from leaking the
// Activity or BroadcastReceiver if someone passes one in.
mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
}
return mRequestQueue;
}
How do I avoid the above code duplication when attaching the bearer token in every request?
public class CustomJsonRequest extends JsonRequest<Object>{
public CustomJsonRequest(String url, String requestBody, Response.Listener<Object> listener,
Response.ErrorListener errorListener) {
super(url, requestBody, listener, errorListener);
}
public CustomJsonRequest(int method, String url, String requestBody, Response.Listener<Object> listener,
Response.ErrorListener errorListener) {
super(method, url, errorListener);
}
#Override
protected Response<Object> parseNetworkResponse(NetworkResponse response) {
return Response.success(Object, HttpHeaderParser.parseCacheHeaders(response));
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<String, String> ();
TokenService tokenservice = new TokenService(ctx);
String accesstoken = tokenservice.getToken(ApiHelper.ACCESS_TOKEN_SHARED_PREF);
headers.put("Authorization", "Bearer " + accesstoken);
return headers;
}
}
You can extend JsonRequest class and override getHeaders() method.
Pass instance of CustomJsonRequest object when you are adding volley requests in queue.
VolleyUtils.getInstance().addToRequestQueue(customJsonRequest);
You can write a "Factory" with a method that takes your checkauthurl and ctx and returns you an instance of the JsonObjectRequest. Your factory could implement some logic for re-use of objects that have the same auth Url if that makes sense in your case.
You can sub-class JsonObjectRequest and provide your checkauthurl and ctx as a parameter to the constructor. Similarly, you can implement a scheme to re-use the objects
The factory would be the suggested approach if you want Dependency Injection.
I would recommend against pre-allocating the Token and using it in multiple requests. Tokens expire. If the TokenService is written well, it should know when tokens will expire and refresh as needed (if possible).
Make an AppController.java file and mention this file name as android:app in manifest tag.
public class AppController extends Application {
public static final String TAG = AppController.class.getSimpleName();
private RequestQueue mRequestQueue;
private static AppController mInstance;
private ImageLoader mImageLoader;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized AppController getInstance() {
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public ImageLoader getImageLoader() {
getRequestQueue();
if (mImageLoader == null) {
mImageLoader = new ImageLoader(this.mRequestQueue, new LruBitmapCache());
}
return this.mImageLoader;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
Do the networking code
StringRequest strReq = new StringRequest(Request.Method.POST, AppConfig.URL_BUYER_LOGIN,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
protected Map<String, String> getParams() {
}
};
// Adding request to request queue
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
}
Related
I try to write app which parse decoding of abbreviations and frequency of their use. User input abbreviation, for example "kg". So, app should connect to "http://nactem.ac.uk/software/acromine/dictionary.py?sf=kg" and parse it.
What should model classes look like? Did I describe #Geth correctly in the interface? How can I get the list, I made an adapter, bind it to the list, but I'm not sure about getResponse ().
Interface:
public interface SService {
#GET("dictionary.py?")
Call<Example> getResponse(#Query("sf=") String searchString);
}
Retrofit client:
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl) {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
And addition class ApiUtils
public class ApiUtils {
public static final String BASE_URL = "http://nactem.ac.uk/software/acromine/";
public static SService getSOService() {
return RetrofitClient.getClient(BASE_URL).create(SService.class);
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
private ArrayList<Lf> elements = new ArrayList();
EditText editText1;
ElementAdapter stateAdapter;
ListView list;
private SService mService;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText1 = (EditText) findViewById(R.id.edit_text);
mService = ApiUtils.getSOService();
list = (ListView) findViewById(R.id.fragment_list);
stateAdapter = new ElementAdapter(this, R.layout.list_item, elements);
list.setAdapter(stateAdapter);
}
public void loadAnswers() {
mService.getResponse(editText1.getText().toString()).enqueue(new Callback<Example>() {
#Override
public void onResponse(Call<Example> call, Response<Example> response) {
if(response.isSuccessful()) {
stateAdapter.updateAnswers(response.body().getLfs());
} else {
int statusCode = response.code();
// handle request errors depending on status code
}
}
#Override
public void onFailure(Call<Example> call, Throwable t) {
}
});
}
public void activity_button(View view) {
//stateAdapter.clear();
loadAnswers();
}
}
UPD!!
All input data is an array: Array[Object{...}]. Right interface for parsing it:
public interface SService {
#GET("dictionary.py")
Call<List<Example>> getResponse(#Query("sf") String searchString);
}
So, we get with Call List with Example object (Only one object in this case).
Change the SService interface to the following,
public interface SService {
#GET("dictionary.py")
Call<Example> getResponse(#Query("sf") String searchString);
}
I need to remove the soapAction from this header:
Headers: {Accept=[*/*], SOAPAction ["http://www.ya.ru/mybank/method/getDollars"]}
My configuration looks like this:
#PostConstruct
public void initialization(){
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(MyClass.class);
factory.setAddress(myWsdlUrl);
service = (MyClass) factory.create();
Client client = ClientProxy.getClient(service);
}
#Bean
public SAAJMetaFactory messageFactory(){
return new SAAJMetaFactoryImpl();
}
In the class of service I make such a request:
#Service
public class MyIntegrationImpl implements MyIntegration {
private MyClass service;
public MyIntegrationImpl(MyClass service) {
this.service = service;
}
#Override
public Info getVpc(ReqClass req, String clientPhone) {
return service.getInfo(req, clientPhone);
}
}
I found this code, but I do not know how to apply it:
public class RemoveActionHandler implements SOAPHandler<SOAPMessageContext> {
#Override
public Set<QName> getHeaders() {
System.out.println("Server : getHeaders()");
return null;
}
#Override
public boolean handleMessage(SOAPMessageContext context) {
if ("".equals(context.get(BindingProvider.SOAPACTION_URI_PROPERTY)))
context.put(BindingProvider.SOAPACTION_URI_PROPERTY, null);
return true;
}
#Override
public boolean handleFault(SOAPMessageContext context) {
System.out.println("Server : handleFault()");
return true;
}
#Override
public void close(MessageContext context) {
System.out.println("Server : close()");
}
}
This code can remove the required header
It was necessary to create an interceptor:
public class ServiceMyInterceptor extends AbstractSoapInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(ServiceMyInterceptor.class);
public ServiceMyInterceptor() {
super(Phase.USER_PROTOCOL);
addAfter(ReadHeadersInterceptor.class.getName());
addAfter(EndpointSelectionInterceptor.class.getName());
}
#Override
public void handleMessage(SoapMessage message) throws Fault {
Map<String, List<String>> headers = CastUtils.cast((Map)message.get(Message.PROTOCOL_HEADERS));
if (headers != null) {
List<String> sa = headers.get("SOAPAction");
String action = null;
if (sa != null && sa.size() > 0) {
action = sa.get(0);
}
LOGGER.info("Remove SOAPAction who equals {}", action);
headers.remove("SOAPAction");
}
}
}
And apply it this way:
#PostConstruct
public void initialization(){
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(MyClass.class);
factory.setAddress(myWsdlUrl);
service = (MyClass) factory.create();
Client client = ClientProxy.getClient(service);
ServiceMyInterceptor interceptor = new ServiceMyInterceptor();
client.getEndpoint().getOutInterceptors().add(interceptor);
}
If you judge by logs, then the SOAPAction header is gone.
I get Android volley error suddenly when i run my program.here i paste my AppController class for handling the volley objects.
AppController.java
public class AppController extends Application {
public static final String TAG = AppController.class.getSimpleName();
private RequestQueue mRequestQueue;
private static AppController mInstance;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized AppController getInstance() {
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
and i call this class in some another class of my program like
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
it will executed without any errors in so many days but now it shows error
like
Error:
java.lang.NoSuchMethodError: No virtual method setTag(Ljava/lang/Object;)Lcom/android/volley/Request; in class Lcom/android/volley/Request or its super classes (declaration of 'com.android.volley.Request'; appears in /data/app/com.example.rninja4.rookie-1/split_lib_dependencies_apk.apk:classes6.dex)
at com.example.packagename.App.AppController.addToRequestQueue(AppController.java:39)
You have not declared application class in manifest like below.
<application
android:name="AppController"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
I am using Loopj AsyncHttpLibrary for an android application. My purpose is to show a page containing some questions and corresponding answers. The Rest API, that I am coding against, serves questions and answers at different endpoints as:
http://example.com/docs/{id}/questions
http://example.com/docs/{id}/answers
What I'm doing right now is to make an async http request for "questions", then in the success callback of the first request, I do the second request to fetch "answers". Here is my cleaned code:
MyApiClient.getQuestions(docId, new JsonHttpResponseHandler() {
#Override
public void onSuccess(JSONObject questionsResponse) {
MyApiClient.getAnswers(docId, new JsonHttpResponseHandler() {
#Override
public void onSuccess(JSONObject answersResponse) {
.... Do stuff ....
}
});
}
});
where MyApiClient is a static wrapper for the AsyncHttpLibrary as recommended in the library's documentation, it looks like this:
public class MyApiClient {
private static final String BASE_URL = "http://example.com/";
private static AsyncHttpClient client = new AsyncHttpClient();
public static void get(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
client.get(getAbsoluteUrl(url), params, responseHandler);
}
public static void post(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
client.post(getAbsoluteUrl(url), params, responseHandler);
}
public static void getQuestions(long docId, AsyncHttpResponseHandler responseHandler) {
get("docs/" + String.valueOf(docId) + "/questions" , null, responseHandler);
}
public static void getAnswers(long docId, AsyncHttpResponseHandler responseHandler){
get("docs/" + String.valueOf(docId) + "/answers" , null, responseHandler);
}
private static String getAbsoluteUrl(String relativeUrl) {
return BASE_URL + relativeUrl;
}
}
Is there a way to start both requests without one waiting for the other to execute?
I also need to be able use both http results in the same context (populating ui).
After some struggling, I found it was not that hard to hold a state of the network operations in my activity class. I ended up using two boolean vars: "fetchedQuestions" and "fetchedAnswers", which are reset to 'false ' before initializing network requests. Both requests are sent simultaneously and in their success methods, I check if the other request is finalized or not.
Here is the code (using Loopj AsyncHttpClient library)
public class MyActivity extends Activity {
private boolean fetchedQuestions;
private boolean fetchedAnswers;
private JSONObject questions;
private JSONObject answers;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
refresh();
}
private void refresh(){
fetchedQuestions = false;
fetchedAnswers = false;
long docId = 1;
MyApiClient.getQuestions(docId, new JsonHttpResponseHandler() {
#Override
public void onSuccess(JSONObject questionsResponse) {
questions = questionsResponse;
fetchedQuestions = true;
if (fetchedAnswers)
populatePage();
}
});
MyApiClient.getAnswers(docId, new JsonHttpResponseHandler() {
#Override
public void onSuccess(JSONObject answersResponse) {
answers = answersResponse;
fetchedAnswers = true;
if (fetchedQuestions)
populatePage();
}
});
}
private void populatePage(){
// do stuff with "questions" and "answers"
}
}
where MyApiClient is defined as
public class MyApiClient {
private static final String BASE_URL = "http://example.com/";
private static AsyncHttpClient client = new AsyncHttpClient();
public static void get(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
client.get(getAbsoluteUrl(url), params, responseHandler);
}
public static void post(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
client.post(getAbsoluteUrl(url), params, responseHandler);
}
public static void getQuestions(long docId, AsyncHttpResponseHandler responseHandler) {
get("docs/" + String.valueOf(docId) + "/questions" , null, responseHandler);
}
public static void getAnswers(long docId, AsyncHttpResponseHandler responseHandler){
get("docs/" + String.valueOf(docId) + "/answers" , null, responseHandler);
}
private static String getAbsoluteUrl(String relativeUrl) {
return BASE_URL + relativeUrl;
}
}
Hope this helps:
public class SampleActivity extends Activity{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new GetQuestionsThread().execute();
new GetAnswersThread().execute();
}
public class GetQuestionsThread extends AsyncTask<Void, Void, String> {
public GetQuestionsThread() {
}
#Override
protected String doInBackground(Void... params) {
//make post
return request;
}
#Override
protected void onPostExecute(LString result) {
// do something with result
}
}
public class GetAnswersThread extends AsyncTask<Void, Void, String> {
public GetAnswersThread() {
}
#Override
protected String doInBackground(Void... params) {
//make post
return request;
}
#Override
protected void onPostExecute(LString result) {
// do something with result
}
}
}
Good evening. I have some troubles with getting response.
I have two classes:
MyHttpClient with method get(), and String for response.
public class MyHttpClient {
private static final String BASE_URL = "http://pgu.com";
private static String response;
private static AsyncHttpClient client = new AsyncHttpClient();
public static void get(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
client.get(getAbsoluteUrl(url), params, responseHandler);
}
private static String getAbsoluteUrl(String relativeUrl) {
return BASE_URL + relativeUrl;
}
public static String getResponse() {
return response;
}
public static void setResponse(String response) {
response = response;
}
}
In second class I'm using GET method. Html is printing in LogCat, but setResponse doesn't work. How can I get the response String as a field of MyHttpClient ?
public class MyHttpClientUsage {
public MyHttpClientUsage(){
}
public void getInfoAbout() throws HttpException{
RequestParams params = new RequestParams();
params.put("a", "Static");
params.put("content", "47");
MyHttpClient.get("", params, new AsyncHttpResponseHandler(){
#Override
public void onSuccess(String response) {
System.out.println(response);
//Write HTML in LogCat(work)
MyHttpClient.setResponse(response); //doesn't work
}
});
}
}
you need to use this.response = response in MyHttpClient as currently you are just resetting the parameter that you're sending into the method.
It's good practice to set your method parameters as final to avoid this.