I am trying to load an image from url, but adding authorization token. Picasso does not want at all to load it if i add networkPolicy(NetworkPolicy.OFFLINE) is there any problem with it ?
my code :
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder()
.addHeader("Authorization", "Bearer " + userPrefs.accessToken().get())
.build();
return chain.proceed(newRequest);
}
})
.build();
Picasso picasso = new Picasso.Builder(getActivity())
.downloader(new OkHttp3Downloader(client))
.build();
picasso
.load(URL)
.networkPolicy(NetworkPolicy.OFFLINE)
.into(ivUserImage, new Callback() {
#Override
public void onSuccess() {
Toast.makeText(getActivity(), "+", Toast.LENGTH_SHORT).show();
}
#Override
public void onError() {
Toast.makeText(getActivity(), "-", Toast.LENGTH_SHORT).show();
}
});
Yes, it is
We have three enums to pass to networkPolicy
NO_CACHE
Skips checking the disk cache and forces loading through the network.
NO_STORE
Skips storing the result into the disk cache.
OFFLINE
Forces the request through the disk cache only, skipping network.
So if we use OFFLINE, It will skip the Network.
Also please read this API for Picasso
The easy way to use the offline policy
Picasso.with( getApplicationContext() ).load( link ).networkPolicy( NetworkPolicy.OFFLINE ).placeholder( R.drawable.notification ).into( imageView, new Callback() {
#Override
public void onSuccess()
{
}
#Override
public void onError() {
Picasso.with( getApplicationContext() ).load( link ).placeholder( R.drawable.notification ).into( imageView );
}
} );
Related
This question basically wants to know how to use stored cookies for subsequent request. The long text below is just for example. Basic question is how to use the same cookie for all requests on a particular website.
Basically I am trying to reach the login page of a website within the android app. The website works the following way.
There are 3 urls to consider.
1 -> "http://www.example.com/timeoutPage"
2 -> "http://www.example.com/mainPage"
3 -> "http://www.example.com/loginPage"
The two main points to consider are
(1) If we directly go to the 3rd url (loginPage), it redirects to the 1st url(timeoutPage). The timeoutPage has a button to go to the mainPage.
(2) If we go to the 2nd url (mainPage), it gives us a cookie. Now, after getting the cookie, when we visit the 3rd url (loginPage), we are able to access it. The loginPage has a captcha so it's essential to visit it(loginPage) in order to login.
Without the cookie, which is given at visiting 2nd url(mainPage), we cannot directly access 3rd url(loginPage).
so what i am doing is to make a ClearableCookieJar and attach it to OkHttpClient.
OkHttpClient client;
ClearableCookieJar cookieJar;
CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(this));
client = new OkHttpClient.Builder()
.cookieJar(cookieJar)
.build();
Request request = new Request.Builder()
.url("http://www.example.com/mainPage")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
textView.setText("Failed to get response");
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()){
final String myResponse = response.body().string();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText(myResponse);
}
});
}
}
});
Everthing is fine till here as i am able to print the html of mainPage in my textview.
Problem starts here when i make another request for the loginPage.
request = new Request.Builder()
.url("http://www.example.com/loginPage")
.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
textView.setText("Failed to get response");
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()){
final String myResponse2 = response.body().string();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText(myResponse2);
}
});
}
}
});
Here i again make a request to the loginPage but i reach the timeoutPage. How should i make the request for the loginPage url so that my request sends the cookie which i stored in the cookieJar while making a request to mainPage. One way i thought of was
request = new Request.Builder()
.url("http://www.example.com/loginPage")
.addHeader("Cookie", cookieStringGivenAtMainPage)
.build();
But i don't know how to access that cookieStringGivenAtMainPage. How should i reach that loginPage?
I print the html of the response to see if i reached the correct page.
It seems the answer you want to know is the singleton pattern.
Please refer to below sample code. I got it from kakao developer site about 3 years ago.
public class NetworkManager {
private static NetworkManager instance;
private OkHttpClient client;
/**
* By using Singleton Pattern we can share cookie, client values.
**/
private NetworkManager() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
Context context = GlobalApplication.getGlobalApplicationContext();
ClearableCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(context));
builder.cookieJar(cookieJar);
builder.followRedirects(true);
builder.addInterceptor(new RedirectInterceptor());
File cacheDir = new File(context.getCacheDir(), "network");
if (!cacheDir.exists()) {
cacheDir.mkdir();
}
Cache cache = new Cache(cacheDir, 10 * 1024 * 1024);
builder.cache(cache);
builder.connectTimeout(30, TimeUnit.SECONDS);
builder.readTimeout(10, TimeUnit.SECONDS);
builder.writeTimeout(10, TimeUnit.SECONDS);
client = builder.build();
}
public static NetworkManager getInstance() {
if (instance == null) {
instance = new NetworkManager();
}
return instance;
}
public OkHttpClient getClient() {
return client;
}
}
In addition below is sample usage.
OkHttpClient client = NetworkManager.getInstance().getClient();
RequestBody formBody = new FormBody.Builder()
.add("userId", getTargetUserId())
.build();
Request request = new Request.Builder()
.url("www.test.com/insert.php")
.post(formBody)
.build();
client.newCall(request).enqueue(callback);
I need to get the XML file from the site. I'm learning to use Retrofit.
I need to make a request and attach my API key via the "X-AppId" header. It should look like this:
X-AppId: my key.
If I do this from the browser, I get the answer.
Through the retrofit I get the access
error 403 Forbidden code = 403, message = Forbidden, url = https: //
Tell me how it is implemented properly to receive an answer from the server code = 200
Here is my implementation:
public interface myAPIinterface {
#GET("/api/ru/index/route/?from=Minsk&to=Warsaw")
Call<Routes> getProducts();
}
This is the activity where I output to the log:
private void getProducts(){
final ProgressDialog loading = ProgressDialog.show(this,"Fetching Data","Please wait...",false,false);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
Log.d(TAG, "getProducts");
httpClient.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
.addHeader("X-AppId:", "97377f7b702d7198e47a2bf12eec74")
.build();
return chain.proceed(request);
}
});
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://rasp.rw.by")
.addConverterFactory(SimpleXmlConverterFactory.create())
.build();
myAPIinterface api = retrofit.create(myAPIinterface.class);
Call<Routes> call = api.getProducts();
call.enqueue(new Callback<Routes>() {
#Override
public void onResponse(#NonNull Call<Routes> call, #NonNull Response<Routes> response) {
Log.d(TAG, "onResponse");
Log.d(TAG, String.valueOf(kk));
Log.d(TAG, String.valueOf(response));
loading.dismiss();}
#Override
public void onFailure(Call<Routes> call, Throwable throwable) {
loading.dismiss();
Log.d(TAG, "onFailure" + throwable);
}
});
this is a log:
Response{protocol=http/1.1, code=403, message=Forbidden,
url=https://rasp.rw.by/api/ru/index/route/?from=Minsk&to=Warsaw}
if I take third-party sites where there are no headers, I get a response of 200 without problems. What am I doing wrong in this case? Thank you.
Oh, man, what are you doing. You can use annotations like #Query, #Header, etc.
public interface myAPIinterface {
#GET("/api/ru/index/route")
Call<Routes> getProducts(#Header("X-AppId:") String YOUR_APP_ID,
#Query("from") String from,
#Query("to") String to)
}
Then you can create request like this:
Retrofit retrofit = new Retrofit.Builder().
.baseUrl("https://rasp.rw.by")
.addConverterFactory(SimpleXmlConverterFactory.create())
.build();
retrofit.create(myAPIinterface.class).getProducts(myId, "Minsk", "Warsaw").enqueue ...
How It can help? You forgot to add header at second retrofit and then you have 403 error. So, You must add annotations, and this will be the last mistake when you forgot to put value to header/query/etc.
I am using Picasso to download images and show them from the server. I need to set basic Aucathention to my requests. And because of that i used this:
'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'
and my code is:
String url = "images/download/" + images.getiId();
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder()
.addHeader("user_auth", user_auth)
.addHeader("user_password", user_pass)
.build();
return chain.proceed(newRequest);
}
})
.build();
Picasso picasso = new Picasso.Builder(context)
.downloader(new OkHttp3Downloader(client))
.build();
picasso.load(url)
.error(R.drawable.error_icon_128)
.into(view);
}
but every time it can't download images And I can't see response code from the server. How can I see response code?
Thank you.
In my application I'm using custom downloader to download images because server requires additional authorisation in request header. I'm trying to load downloaded images in offline mode, but when I'm using this custom downloader Picasso isn't loading images. Anyone could help?
OkHttpClient picassoClient = new OkHttpClient();
picassoClient.interceptors().add(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder()
.addHeader(RestUtils.HEADER, hash)
.build();
return chain.proceed(newRequest);
}
}
);
Picasso picasso = new Picasso.Builder(mContext)
.downloader(new OkHttpDownloader(picassoClient)).build();
picasso.setIndicatorsEnabled(true);
picasso.invalidate(RestUtils.getUrl(url));
if (DeviceUtility.isOnline(mContext)) {
picasso.load(RestUtils.getUrl(url))
.networkPolicy(
DeviceUtility.isOnline(mContext) ?
NetworkPolicy.NO_CACHE : NetworkPolicy.OFFLINE)
.resize(200, 200)
.centerCrop()
.into(viewHolder.mImgvPicture);
} else {
picasso.load(RestUtils.getUrl(url))
.networkPolicy(
DeviceUtility.isOnline(mContext) ?
NetworkPolicy.NO_CACHE : NetworkPolicy.OFFLINE)
.resize(200, 200)
.centerCrop()
.into(viewHolder.mImgvPicture);
}
You invalidate the URL right before getting it from cache:
picasso.invalidate(RestUtils.getUrl(url));
Try to invalidate only if the device is connected.
I use Picasso to download images from the web, and display them in a RecyclerView.
private Picasso createPicasso(Context context){
OkHttpClient picassoClient = new OkHttpClient();
picassoClient.interceptors().add(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
try {
Map authHeaders = BackendServiceClient.buildAuthHeaders();
Request newRequest = chain.request().newBuilder()
.addHeader("Authorization", (String) authHeaders.get("Authorization"))
.build();
return chain.proceed(newRequest);
} catch (CredentialNotStoredException e) {
e.printStackTrace();
}
return chain.proceed(chain.request().newBuilder().build());
}
});
return new Picasso.Builder(context)
.downloader(new OkHttpDownloader(picassoClient))
.build();
}
Usage:
ImageDownloader.getSharedInstance().getPicasso(context)
.load(url)
.placeholder(R.drawable.head_big) //
.error(R.drawable.head_big) //
.tag(context)
.into(holder.personPhoto);
Downloading and displaying the images works as expected, but if I scroll through the list, the images gets fetched from the web again and were not cached.
How is it possible to always cache them on the disk and memory.
Switched to Glide which improves memory footprint and caching works out of the box.
https://github.com/bumptech/glide
http://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en