我正在使用picasso
库来下载位图,因此在api中我需要在标头中传递令牌。我试过这个帖子Android Picasso library, How to add authentication headers?
public static Picasso getImageLoader(final Context context) {
// fetch the auth value
sSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
Picasso.Builder builder = new Picasso.Builder(context);
builder.downloader(new OkHttpDownloader(context) {
@Override
protected HttpURLConnection openConnection(Uri uri) throws IOException {
HttpURLConnection connection = super.openConnection(uri);
connection.setRequestProperty(Constant.HEADER_X_API_KEY, sSharedPreferences.getString(SharedPreferenceKeys.JSESSIONID, ""));
return connection;
}
});
sPicasso = builder.build();
return sPicasso;
}
mTarget = new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom loadedFrom) {
mdpImageView.setImageBitmap(bitmap);
Logger.d(TAG, "Test");
}
@Override
public void onBitmapFailed(Drawable drawable) {
Logger.d(TAG, "Test");
}
@Override
public void onPrepareLoad(Drawable drawable) {
Logger.d(TAG, "Test");
}
};
CustomPicasso.getImageLoader(getActivity()).with(getActivity()).load(URL).into(mTarget);
我调试了我的代码&我看到它从未调用openconnection
的{{1}}覆盖方法,所以我的请求总是失败&最后它调用OkHttpDownloader
。
请帮助我正确传递标题值所需要做的事情。
提前致谢。
答案 0 :(得分:7)
花了两天时间来解决这个问题。对于自定义下载程序,您无需调用with
方法,因为这会初始化默认下载程序&毕加索实例。只需在下面这样做就可以帮助你获得位图。
Picasso.Builder builder = new Picasso.Builder(getActivity());
picasso = builder.downloader(new OkHttpDownloader(getActivity()) {
@Override
protected HttpURLConnection openConnection(Uri uri) throws IOException {
HttpURLConnection connection = super.openConnection(uri);
connection.setRequestProperty(Constant.HEADER_X_API_KEY, mSharedPreferences.getString(SharedPreferenceKeys.JSESSIONID, ""));
return connection;
}
}).build();
picasso.load(url).into(mTarget);
答案 1 :(得分:1)
我有同样的问题,但在我的情况下,我忘记了我的服务器上有一个自签名证书,所以OkHttp获得了证书,然后拒绝检索任何图像。因此,从服务器端来看,毕加索似乎没有提出任何要求。
所以解决方法是创建一个不测试证书的不安全的OkHttp客户端:
static OkHttpClient getUnsafeOkHttpClient() {
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain,
String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain,
String authType) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
} };
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setSslSocketFactory(sslSocketFactory);
okHttpClient.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
return okHttpClient;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
然后在我的CustomOkHttpDownloader中使用它:
static class CustomOkHttpDownloader extends OkHttpDownloader {
private String accessToken;
public CustomOkHttpDownloader(Context context, String accessToken) {
super(getUnsafeOkHttpClient());
this.accessToken = accessToken;
}
@Override
protected HttpURLConnection openConnection(final Uri uri) throws IOException {
HttpURLConnection connection = super.openConnection(uri);
connection.setRequestProperty("Authorization", "Bearer " + accessToken);
Log.d(LOG_TAG, "Creating connection for " + uri + " with " + accessToken);
return connection;
}
}
答案 2 :(得分:0)
Picasso picasso;
Builder builder = new Picasso.Builder(this);
picasso = builder.loader(new BasicAuthOkHttpLoader(this)).build();
将Loader实现为BasicAuthOkHttpLoader类。
在覆盖Load方法中,编写ur身份验证逻辑。
@Override
public Response load(String url, boolean localCacheOnly) throws IOException {
HttpURLConnection connection = client.open(new URL(url));
String authString = "username:password";
String authStringEnc = Base64.encodeToString(authString.getBytes(), Base64.NO_WRAP);
connection.setRequestProperty("Authorization", "Basic " + authStringEnc);
connection.setUseCaches(true);
// no caching happens without this setting in our scenario
connection.setRequestProperty("Cache-Control", "max-stale=2592000");// 30 days
if (localCacheOnly) {
connection.setRequestProperty("Cache-Control", "only-if-cached");
}
boolean fromCache = parseResponseSourceHeader(connection.getHeaderField(RESPONSE_SOURCE));
return new Response(connection.getInputStream(), fromCache);
}
答案 3 :(得分:0)
我使用了另一个库AQuery,并且不仅可以在几分钟内获得对picassa滚动的授权访问权限,而且库也使用了手机凭证,因此非常容易。
即使您不使用此库,也请查看我如何获得仅包含下面所需字段的实验方法。较小的结果使得网络io更快,CPU的差异也很大。由于JSON较小,因此解析速度较快,或者xml的DOM较小,因此构建速度非常快。
我在这里使用的实验方法只为XML中的用户返回我想要的公开相册字段。
GoogleHandle handle = new GoogleHandle(this.getActivity(),
AQuery.AUTH_PICASA, AQuery.ACTIVE_ACCOUNT);
// experimental fields method encoding the data part of the query string only.
String url = "";
try {
url = "https://picasaweb.google.com/data/feed/api/user/default?kind=album&access=public&fields="
+ URLEncoder
.encode("entry(title,id,gphoto:numphotosremaining,gphoto:numphotos,media:group/media:thumbnail)",
"UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
//whatever I know this will work
// I hard coded the string.
}
aq.auth(handle).progress(R.id.pbTrackerAlbumsProgress)
.ajax(url, XmlDom.class, this, "renderAlbums");
public void renderAlbums(String url, XmlDom xml, AjaxStatus status) {
List<PicasaAlbum> entries = convertAll(xml);
if (entries.size() > 0) {
isAuthError = false;
// if the xml iis null we can't display the list
// we can setup the adapter
aa = new ArrayAdapter<PicasaAlbum>(this.getActivity(),
R.layout.listview_item_album, entries) {
public View getView(int position, View convertView,
ViewGroup parent) {
if (convertView == null) {
// convertView =
// View.inflate(getActivity().getBaseContext(),
// R.layout.listview_item_album, parent);
convertView = getActivity().getLayoutInflater()
.inflate(R.layout.listview_item_album, parent,
false);
}
PicasaAlbum picasaAlbum = getItem(position);
AQuery aqLocal = aq.recycle(convertView);
aqLocal.id(R.id.albumTitle).text(picasaAlbum.title);
// aq.id(R.id.meta).text(picasaAlbum.author);
String tbUrl = picasaAlbum.thumbNailUrl.toString();
Bitmap placeholder = aqLocal
.getCachedImage(R.drawable.ic_launcher2);
if (aqLocal.shouldDelay(position, convertView, parent,
tbUrl)) {
aqLocal.id(R.id.tb).image(placeholder);
} else {
aqLocal.id(R.id.tb).image(tbUrl, true, true, 0,
R.drawable.ic_launcher2x, placeholder,
AQuery.FADE_IN_NETWORK, 0);
}
return convertView;
}
};
((TextView) view.findViewById(R.id.tvTrackerExistingAlbum))
.setText("Select the album for route marker photos");
((ProgressBar) view.findViewById(R.id.pbTrackerAlbumsProgress))
.setVisibility(View.GONE);
ListView lv = (ListView) view.findViewById(R.id.lvTrackerAlbums);
lv.setAdapter(aa);
aa.notifyDataSetChanged();
lv.setVisibility(View.VISIBLE);
}
}
答案 4 :(得分:0)
Picasso 2.5,okHttpDownloader已经改变。请参阅以下链接添加身份验证标题
答案 5 :(得分:0)
这最终对我有用,只需调用它然后使用picasso实例,在这里我添加一个访问令牌。但您也可以添加用户名和密码。
private void setupPicasso()
{
//need to set picasso up to use auth - took a while to work this out!
final Context c = context;
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
String token = <token you got when you logged in>;
String authString = "Bearer "+token;
Request newRequest = chain.request().newBuilder()
.addHeader("Authorization", authString)
.build();
return chain.proceed(newRequest);
}
})
.build();
picasso = new Picasso.Builder(context)
.downloader(new OkHttp3Downloader(client))
.build();
}