一切都在标题中,我不明白为什么我的代码在模拟器中工作但在我的设备上不起作用。它抛出“信任锚未找到异常”!怎么可能?我尝试了关于trustManager的okhttp.builder的实现,但仍然..请帮助!!
这是我的班级:
public abstract class NewsFragment extends Fragment {
private static final String TAAG = NewsFragment.class.getSimpleName();
protected ItemAdapter mArticleAdapter;
protected RecyclerView mRecyclerView;
protected NewsFragment.OnNewSelectedInterface mListener;
protected ItemAdapter.OnNewsInsertedInterface mListener2;
protected RecyclerView.LayoutManager mManager;
protected SwipeRefreshLayout mSwipeRefreshLayout;
public static final String KEY_LIST = "key_list";
public interface OnNewSelectedInterface {
void onListNewSelected(int index, ArrayList<Article> articles);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
setHasOptionsMenu(true);
View view = inflater.inflate(R.layout.list_present_news, container, false);
mListener = (NewsFragment.OnNewSelectedInterface) getActivity();
mListener2 = (ItemAdapter.OnNewsInsertedInterface) getActivity();
mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeContainer);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerview);
mManager = new LinearLayoutManager(getActivity());
mArticleAdapter = new ItemAdapter(getActivity(), new ArrayList<>(), mListener, mListener2);
if (!isNetworkAvailable()) alertUserAboutError();
mRecyclerView.setAdapter(mArticleAdapter);
mRecyclerView.setLayoutManager(mManager);
mSwipeRefreshLayout.setRefreshing(true);
new Downloader().execute(getUrl());
//new Downloader().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, getUrl());
refreshData();
setDividerRecyclerView();
return view;
}
private void setDividerRecyclerView() {
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView
.getContext(), DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
}
private void alertUserAboutError() {
AlertDialogFragment alertDialogFragment = new AlertDialogFragment();
alertDialogFragment.show(getActivity().getFragmentManager(), "error_dialog");
}
protected abstract String[] getUrl();
private boolean isNetworkAvailable() {
ConnectivityManager manager = (ConnectivityManager)
getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
boolean isAvailable = false;
if (networkInfo != null && networkInfo.isConnected()) {
isAvailable = true;
}
return isAvailable;
}
private void refreshData() {
mSwipeRefreshLayout.setOnRefreshListener(() -> {
mArticleAdapter.clear();
new Downloader().execute(getUrl());
});
mSwipeRefreshLayout.setColorSchemeResources(
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
}
private class Downloader extends AsyncTask<String, Void, ArrayList<Article>> {
ArrayList<Article> mArticleArrayList = new ArrayList<>();
OkHttpClient mClient = new OkHttpClient();
@Override
protected ArrayList<Article> doInBackground(String... strings) {
for (String aMUrl : getUrl()) {
Request mRequest = new Request.Builder().url(aMUrl).build();
try {
Response response = mClient.newCall(mRequest).execute();
try {
if (response.isSuccessful()) {
String json = response.body().string();
mArticleArrayList = getMultipleUrls(json);
}
} catch (IOException | JSONException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return mArticleArrayList;
}
@Override
protected void onPostExecute(ArrayList<Article> articles) {
mArticleAdapter.addAll(articles);
mSwipeRefreshLayout.setRefreshing(false);
Log.v(TAAG, String.valueOf(mArticleAdapter.getItemCount()));
}
private ArrayList<Article> getMultipleUrls(String jsonData) throws JSONException {
if (mArticleArrayList == null || mArticleArrayList.size() == 0) {
mArticleArrayList = getArticleForecast(jsonData);
} else {
mArticleArrayList.addAll(getArticleForecast(jsonData));
}
return mArticleArrayList;
}
private ArrayList<Article> getArticleForecast(String jsonData) throws JSONException {
JSONObject forecast = new JSONObject(jsonData);
JSONArray articles = forecast.getJSONArray("articles");
ArrayList<Article> listArticles = new ArrayList<>(articles.length());
for (int i = 0; i < articles.length(); i++) {
JSONObject jsonArticle = articles.getJSONObject(i);
Article article = new Article();
String urlImage = jsonArticle.getString("urlToImage");
article.setTitle(jsonArticle.getString("title"));
article.setDescription(jsonArticle.getString("description"));
article.setImageView(urlImage);
article.setArticleUrl(jsonArticle.getString("url"));
article.setUrlToImage(jsonArticle.getString("urlToImage"));
listArticles.add(i, article);
}
return listArticles;
}
}
}
这是日志:
05-04 23:39:01.382 9856-9997/com.silho.ideo.knewsproject W/System.err: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
05-04 23:39:01.382 9856-9997/com.silho.ideo.knewsproject W/System.err: at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:306)
05-04 23:39:01.382 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:242)
05-04 23:39:01.382 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:200)
05-04 23:39:01.382 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.internal.connection.RealConnection.buildConnection(RealConnection.java:174)
05-04 23:39:01.382 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:114)
05-04 23:39:01.382 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:196)
05-04 23:39:01.382 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:132)
05-04 23:39:01.382 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:101)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:179)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at okhttp3.RealCall.execute(RealCall.java:63)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at com.silho.ideo.knewsproject.Fragments.PresentNews.NewsFragment$Downloader.doInBackground(NewsFragment.java:170)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at com.silho.ideo.knewsproject.Fragments.PresentNews.NewsFragment$Downloader.doInBackground(NewsFragment.java:143)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at android.os.AsyncTask$2.call(AsyncTask.java:288)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:237)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
05-04 23:39:01.383 9856-9997/com.silho.ideo.knewsproject W/System.err: at java.lang.Thread.run(Thread.java:818)
我也在okhttp网站上找到了这个,但它也不起作用:
public OkHttpClient.Builder sslSocketFactory(SSLSocketFactory sslSocketFactory, X509TrustManager信任管理器) 设置用于保护HTTPS连接的套接字工厂和信任管理器。如果未设置,将使用系统默认值。 大多数应用程序不应该调用此方法,而是使用系统默认值。这些类包括特殊优化,如果实现了装饰,可能会丢失这些优化。
如有必要,您可以使用以下代码自行创建和配置默认值:
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:"
+ Arrays.toString(trustManagers));
}
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { trustManager }, null);
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(sslSocketFactory, trustManager);
.build();
答案 0 :(得分:0)
我的 android 应用程序(以及我的 Spring Boot 后端服务器)也遇到了类似的问题。我认为您的问题与您使用的是自签名证书有关。解决方案是将包含受信任证书的信任管理器(采用 PKCS12 格式)嵌入您应用的资产文件夹中。
1. 在 assets 文件夹中添加带有证书的密钥库:
2. 然后以这种方式使用您的嵌入式信任管理器配置 OkHttpClient: (用你的密码修改)
fun getOkHttpClient(context: Context): OkHttpClient {
val password = "keystore_password".toCharArray()
val keyStore = KeyStore
.getInstance("PKCS12").apply {
load(context.assets.open("trust_store.p12"), password)
}
val trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm())
.apply { init(keyStore) }
val keyManagerFactory = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm())
.apply { init(keyStore, password) }
val sslContext = SSLContext.getInstance("SSL")
.apply {
init(keyManagerFactory.keyManagers, trustManagerFactory.trustManagers, SecureRandom())
}
return OkHttpClient.Builder()
.sslSocketFactory(sslContext.socketFactory,
trustManagerFactory.trustManagers[0] as X509TrustManager)
.hostnameVerifier { hostname, _ -> hostname == apiHostname } // Return true if you want to trust all hostnames
.build()
}
如果您想信任所有主机名,只需在 hostnameVerifier
功能块中返回 true,但我不建议您这样做,因为它会使您的应用面临安全威胁。
请注意,使用自定义信任库时,您的应用将仅信任该信任库中包含的证书。