当前位置:   article > 正文

彻底解决Android网络请求失败_android suppressed: com.drake.net.exception.httpfa

android suppressed: com.drake.net.exception.httpfailureexception:

前言

不知道大家是否在项目中遇到过请求网络请求失败的情况,事实上在Android 9.0(API 28)后就谷歌就已经禁止明文访问了,以下方法解决可以这个问题。(我这里默认用OkHttp第三方框架来请求网络)

首先我这边自己封装了一个OkHttp封装类,有需要自取,也可以自己分装提高自己的代码编写能力。注:我在get请求失败的时候捕获了异常,这个注意,后面有用到。

  1. public class MyOkHttp {
  2. private OkHttpClient okHttpClient;
  3. private Gson gson = new Gson();
  4. private volatile static MyOkHttp myOkhttp = null;
  5. private MyOkHttp() {
  6. okHttpClient = new OkHttpClient
  7. .Builder()
  8. .hostnameVerifier(new AllowAllHostnameVerifier())
  9. .sslSocketFactory(TrustAllCerts.createSSLSocketFactory(), TrustAllCerts.getX509TrustManager())
  10. .connectTimeout(10, TimeUnit.SECONDS)//连接超时
  11. .readTimeout(500, TimeUnit.SECONDS)
  12. .build();//读超时 还有一个写超时
  13. }
  14. public static MyOkHttp getInstance() {
  15. if (myOkhttp == null) {
  16. return newInstance();
  17. }
  18. return myOkhttp;
  19. }
  20. private synchronized static MyOkHttp newInstance() {
  21. if (myOkhttp == null) {
  22. myOkhttp = new MyOkHttp();
  23. }
  24. return myOkhttp;
  25. }
  26. public void get(String url, final requestMessage requestMessage) {
  27. final Request request = new Request.Builder().addHeader("Content-Type", "application/json; charset=utf-8").get().url(url).build();
  28. okHttpClient.newCall(request).enqueue(new Callback() {
  29. @Override
  30. public void onFailure(Call call, IOException e) {
  31. requestMessage.requestFail();
  32. requestMessage.requestComplete();
  33. }
  34. @Override
  35. public void onResponse(final Call call, Response response) throws IOException {
  36. requestMessage.requestComplete();
  37. if (response.isSuccessful()) {
  38. requestMessage.requestSuccess(response);
  39. } else {
  40. requestMessage.requestFail();
  41. LogUtils.e(response.message());
  42. }
  43. }
  44. });
  45. }
  46. public void post(String url, Map<String, String> param, final requestMessage requestMessage) {
  47. FormBody.Builder builder = new FormBody.Builder();
  48. if (param != null) {
  49. for (Map.Entry<String, String> entry : param.entrySet()) {
  50. builder.add(entry.getKey(), entry.getValue());
  51. }
  52. }
  53. Request request = new Request.Builder()
  54. .post(builder.build())
  55. .url(url)
  56. .build();
  57. okHttpClient.newCall(request).enqueue(new Callback() {
  58. @Override
  59. public void onFailure(Call call, IOException e) {
  60. LogUtils.d(e.toString());
  61. e.printStackTrace();
  62. requestMessage.requestFail();
  63. requestMessage.requestComplete();
  64. }
  65. @Override
  66. public void onResponse(Call call, Response response) throws IOException {
  67. requestMessage.requestComplete();
  68. if (response.isSuccessful()) {
  69. requestMessage.requestSuccess(response);
  70. } else {
  71. requestMessage.requestFail();
  72. LogUtils.d(response.body().string());
  73. }
  74. }
  75. });
  76. }
  77. public void postBitMap(String url, File file, String assetNumber, final requestMessage requestMessage) {
  78. MultipartBody.Builder builder = new MultipartBody.Builder()
  79. .setType(MultipartBody.FORM);
  80. builder.addFormDataPart("picture", "img.jpg", RequestBody.create(MediaType.parse("image/jpg"), file));
  81. builder.addFormDataPart("assetNumber", assetNumber);
  82. Request request = new Request.Builder()
  83. .url(url)
  84. .post(builder.build())
  85. .build();
  86. okHttpClient.newCall(request).enqueue(new Callback() {
  87. @Override
  88. public void onFailure(Call call, IOException e) {
  89. e.printStackTrace();
  90. requestMessage.requestFail();
  91. requestMessage.requestComplete();
  92. }
  93. @Override
  94. public void onResponse(Call call, Response response) throws IOException {
  95. requestMessage.requestComplete();
  96. if (response.isSuccessful()) {
  97. requestMessage.requestSuccess(response);
  98. } else {
  99. requestMessage.requestFail();
  100. LogUtils.d(response.message());
  101. }
  102. }
  103. });
  104. }
  105. //系统时间获取方法
  106. public String getDate() {
  107. //获取系统的日期时间
  108. Calendar calendar = Calendar.getInstance();
  109. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
  110. return sdf.format(calendar.getTime());
  111. }
  112. //系统时间获取方法
  113. public String getTime() {
  114. //获取系统的日期时间
  115. Calendar calendar = Calendar.getInstance();
  116. String strDateFormat = "yyyy-MM-dd HH:mm:ss";
  117. SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat, Locale.ENGLISH);
  118. return sdf.format(calendar.getTime());
  119. }
  120. public Gson getGson() {
  121. return gson;
  122. }
  123. public interface requestMessage {
  124. void requestFail();
  125. //失败成功都会回调
  126. void requestComplete();
  127. void requestSuccess(Response response) throws IOException;
  128. }
  129. }
1.不用http协议,只采用https协议

以下对比两个协议的区别

  1. public class MainActivity extends AppCompatActivity {
  2. private static final String TAG = "jiangjianhua";
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. setContentView(R.layout.activity_main);
  7. MyOkHttp.getInstance().get("http://www.baidu.com", new MyOkHttp.requestMessage() {
  8. @Override
  9. public void requestFail() {
  10. runOnUiThread(() -> Toast.makeText(MainActivity.this, "连接超时", Toast.LENGTH_SHORT).show());
  11. }
  12. @Override
  13. public void requestComplete() {
  14. }
  15. @Override
  16. public void requestSuccess(Response response) throws IOException {
  17. Log.d(TAG, "response: " + response.body().string());
  18. }
  19. });
  20. }
  21. }

这个demo就只有一个自动生成的主页面,主页面什么都没有,点击启动。

获得结果:CLEARTEXT communication to www.baidu.com not permitted by network security policy  翻译过来就是   网络安全政策不允许CLEARTEXT与www.baudu.com通信。所以就是网络安全的问题。然后https协议默认带有加密,所以用https协议就不会有问题了。在访问URL那里改成https://www.baidu.com就可以了。看结果:

已经获取到了请求体里面的内容了,就证明请求成功了。

2.加上配置文件  network_security_config.xml

在项目中的res资源文件夹中,创建一个xml文件夹,创建一个文件network_security_config.xml。内容如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <network-security-config>
  3. <base-config cleartextTrafficPermitted="true" />
  4. </network-security-config>

在 AndroidManifest.xml文件重加入 android:networkSecurityConfig="@xml/network_security_config" 然后把请求的地址协议改回 http

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.example.mytestdemo">
  4. <uses-permission android:name="android.permission.INTERNET"/>
  5. <application
  6. android:allowBackup="true"
  7. android:icon="@mipmap/ic_launcher"
  8. android:label="@string/app_name"
  9. android:roundIcon="@mipmap/ic_launcher_round"
  10. android:supportsRtl="true"
  11. android:theme="@style/AppTheme"
  12. android:networkSecurityConfig="@xml/network_security_config">
  13. <activity android:name=".MainActivity">
  14. <intent-filter>
  15. <action android:name="android.intent.action.MAIN" />
  16. <category android:name="android.intent.category.LAUNCHER" />
  17. </intent-filter>
  18. </activity>
  19. </application>
  20. </manifest>

完成,然后启动,结果图:

 最后也访问成功了。

所以,访问不了主要是因为涉及到网络安全,既然是网络安全那我们就尽量遵守这个规则,不关是https还是http都加上就好了。这样就能确保两种协议都能访问成功了。(对了,最后提一嘴,把版本退回Android 9.0之前说不定也可以哦,嘻嘻)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/465214
推荐阅读
相关标签
  

闽ICP备14008679号