OKhttp网络请求支持(raw,from-data)提交实战版本更新安装(请求表单,上传图片,上传多张图片)

今天和大家分享一个okhttp网络请求的实战案例,欢迎新手学生,大佬指点,话不多说直接上干货。

我是直接手动添加的架包,手动导入,记住一定要导入。添加依赖也可以哈,看个人爱好(要架包的私信或者留言,留邮箱,或者什么我发给你们)

然后在添加依赖:(允许我装个x用rxjava2了,加载图片用的是glide,支持多张上传图片)

implementation 'io.reactivex.rxjava2:rxjava:2.2.19'
    implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
    implementation 'com.github.bumptech.glide:glide:4.11.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
    implementation 'com.google.code.gson:gson:2.8.5'

最重要的一步来了,记住了 添加网络权限:

!--相机权限-->
    <uses-permission android:name="android.permission.CAMERA" />
    <!--读文件权限-->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <!--使用特性-->
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />
    <uses-permission android:name="android.permission.INTERNET" />

配置的都差不多准备完成了开始干代码吧:用rxjava接口是要有的:

public interface MyNetWorkCallback<T> {

    void onSuccess(T t);
    void onError(int errorCode, String errorMsg);

}

继续在上:

public interface IHttp {
    <T> void get(String url, MyNetWorkCallback<T> callback);
    <T> void get(String url, Map<String, String> params, MyNetWorkCallback<T> callback);
    <T> void get(String url, Map<String, String> params, Map<String, String> headers, MyNetWorkCallback<T> callback);
    <T> void post(String url, Map<String, String> params, MyNetWorkCallback<T> callback);
    <T> void postraw(String url, String params, MyNetWorkCallback<T> callback);
    <T> void postrawfile(String url, File file, MyNetWorkCallback<T> callback);
    void upload(String url, String path, Map<String, String> params, String fileType, MediaType MEDIA_TYPE, final MyNetWorkCallback<String> callback);
    <T> void download(String url,MyNetWorkCallback<String> callback);
    void loadImage(String url, ImageView imageView);

}

这个类干啥来的忘记了,场时间不用了,但是也写山了,你们可以不用

public class HttpFactroy {
    public static IHttp create(){
        return OkHttpUtils.getInstance();
    }
}

主要的类来了,单例走起:

public class OkHttpUtils implements IHttp {

    private OkHttpClient okHttpClient;

    //构造函数私有化
    private OkHttpUtils() {
        okHttpClient = new OkHttpClient.Builder().build();
    }

    private static OkHttpUtils okHttpUtils;

    //提供一个公共的、静态的、返回值类型是当前本类的对象
    public static OkHttpUtils getInstance() {
        if (okHttpUtils == null) {
            synchronized (OkHttpUtils.class) {
                if (okHttpUtils == null) {
                    okHttpUtils = new OkHttpUtils();
                }
            }
        }
        return okHttpUtils;
    }

    private ProgressDialog progressDialog;

    @Override
    public <T> void get(String url, MyNetWorkCallback<T> callback) {

    }

    /**
     * 上传多张图片及参数
     *
     * @param reqUrl   URL地址
     * @param paramssa 参数
     * @param pic_key  上传图片的关键字
     * @return
     */
    public Observable<String> sendMultipart(final String reqUrl, final Map<String, String> paramssa, final String pic_key, final List<File> filessa) {
        return Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<String> emitter) throws Exception {
                MultipartBody.Builder multipartBodyBuilder = new MultipartBody.Builder();
                multipartBodyBuilder.setType(MultipartBody.FORM);
                //遍历map中所有参数到builder
                if (paramssa != null) {
                    for (String key : paramssa.keySet()) {
                        multipartBodyBuilder.addFormDataPart(key, paramssa.get(key));
                    }
                }
                //遍历paths中所有图片绝对路径到builder,并约定key如“upload”作为后台接受多张图片的key
                if (filessa != null) {
                    for (File file : filessa) {
                        multipartBodyBuilder.addFormDataPart(pic_key, file.getName(), RequestBody.create(MEDIA_TYPE_PNG, file));
                    }
                }
                //构建请求体
                RequestBody requestBody = multipartBodyBuilder.build();
                Request.Builder RequestBuilder = new Request.Builder();
                RequestBuilder.url(reqUrl);// 添加URL地址
                RequestBuilder.post(requestBody);
                Request request = RequestBuilder.build();
                okHttpClient.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        emitter.onError(e);
                        emitter.onComplete();
                        call.cancel();
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        String str = response.body().string();
                        emitter.onNext(str);
                        emitter.onComplete();
                        call.cancel();
                    }
                });
            }
        });
    }

    /**
     * 发送get请求
     *
     * @param url      请求地址
     * @param params   请求参数
     * @param callback 回调
     * @param <T>      请求回来的数据对应的JavaBean
     */
    @Override
    public <T> void get(String url, Map<String, String> params, final MyNetWorkCallback<T> callback) {
        StringBuffer sb = new StringBuffer(url);
        if (params != null && params.size() > 0) {
            sb.append("?");
            Set<String> keys = params.keySet();
            for (String key : keys) {
                String value = params.get(key);
                sb.append(key).append("=").append(value).append("&");
            }
            url = sb.deleteCharAt(sb.length() - 1).toString();
        }
        Request request = new Request.Builder().url(url).build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                App.context.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        //执行在主线程
                        callback.onError(404, e.getMessage().toString());
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String jsonData = response.body().string();
                //执行在子线程中
                App.context.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        //执行在主线程
                        callback.onSuccess(getGeneric(jsonData, callback));
                    }
                });
            }
        });
    }

    @Override
    public <T> void get(String url, Map<String, String> params, Map<String, String> headers, final MyNetWorkCallback<T> callback) {

        StringBuffer sb = new StringBuffer(url);
        if (params != null && params.size() > 0) {
            sb.append("?");
            Set<String> keys = params.keySet();
            for (String key : keys) {
                String value = params.get(key);
                sb.append(key).append("=").append(value).append("&");
            }
            url = sb.deleteCharAt(sb.length() - 1).toString();
        }
        Request.Builder builder = new Request.Builder();
        if (headers != null && headers.size() > 0) {
            Set<String> keys = headers.keySet();
            for (String key : keys) {
                String value = headers.get(key);
                builder.addHeader(key, value);
            }
        }
        Request request = builder.url(url).build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                App.context.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        //执行在主线程
                        callback.onError(404, e.getMessage().toString());
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String jsonData = response.body().string();
                //执行在子线程中
                App.context.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        //执行在主线程
                        callback.onSuccess(getGeneric(jsonData, callback));
                    }
                });
            }
        });
    }

    /**
     * post方法上传表单
     *
     * @param url
     * @param params
     * @param callback
     * @param <T>
     */
    @Override
    public <T> void post(String url, Map<String, String> params, final MyNetWorkCallback<T> callback) {
        FormBody.Builder builder = new FormBody.Builder();
        if (params != null && params.size() > 0) {
            Set<String> keys = params.keySet();
            for (String key : keys) {
                String value = params.get(key);
                builder.add(key, value);
            }
        }
        Request request = new Request.Builder().url(url).post(builder.build()).build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                App.context.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        //执行在主线程
                        callback.onError(404, e.getMessage().toString());
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String jsonData = response.body().string();
                //执行在子线程中
                App.context.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        //执行在主线程
                        callback.onSuccess((T) jsonData);
                    }
                });
            }
        });
    }

    /**
     * post方法上传raw表单
     *
     * @param url
     * @param postBody
     * @param callback
     * @param <T>
     */
    @Override
    public <T> void postraw(String url, String postBody, MyNetWorkCallback<T> callback) {
        MediaType MEDIA_TYPE_TEXT = MediaType.parse("application/json; charset=utf-8");
        Request request = new Request.Builder()
                .url(url)
                .post(RequestBody.create(MEDIA_TYPE_TEXT, postBody))
                .build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                App.context.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        //执行在主线程
                        callback.onError(404, e.getMessage().toString());
                    }
                });

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String jsonData = response.body().string();
                App.context.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        //执行在主线程
                        callback.onSuccess((T) jsonData);
                    }
                });
            }
        });
    }

    /**
     * post方法上传raw文件
     *
     * @param url
     * @param file
     * @param callback
     * @param <T>
     */
    @Override
    public <T> void postrawfile(String url, File file, MyNetWorkCallback<T> callback) {
        final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");
        Request request = new Request.Builder()
                .url(url)
                .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))
                .build();

        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                App.context.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        //执行在主线程
                        callback.onError(404, e.getMessage().toString());
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String jsonData = response.body().string();
                App.context.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        //执行在主线程
                        callback.onSuccess((T) jsonData);
                    }
                });
            }
        });
    }


    @Override
    public void upload(String url, String path, Map<String, String> params, String fileType, MediaType MEDIA_TYPE, final MyNetWorkCallback<String> callback) {
        File file = new File(path);
        MultipartBody.Builder multiRequestBody = new MultipartBody.Builder();
        if (params != null && params.size() > 0) {
            Set<String> keys = params.keySet();
            for (String key : keys) {
                String value = params.get(key);
                multiRequestBody.setType(MultipartBody.FORM)
                        .addFormDataPart(key, value);// 提交普通字段
            }
        }
        // 上传文件使用MultipartBody.Builder
        RequestBody requestBody = multiRequestBody
                .setType(MultipartBody.FORM)
                .addFormDataPart(fileType, file.getName(), RequestBody.create(MEDIA_TYPE, file)) // 提交图片,第一个参数是键(name="第一个参数"),第二个参数是文件名,第三个是一个RequestBody
                .build();
        // POST请求
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                App.context.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        //执行在主线程
                        callback.onError(404, e.getMessage().toString());
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String upLoadResult = response.body().string();
                //执行在子线程中
                App.context.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        //执行在主线程
                        callback.onSuccess(upLoadResult);
                    }
                });
            }
        });
    }
private boolean xiazaipanduan=true;
    //下载apk以及安装
    @Override
    public <T> void download(String url, final MyNetWorkCallback<String> callback) {
        if (Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED)) {
            Request request = new Request.Builder().url(url).build();
            OkHttpClient okHttpClient = new OkHttpClient();
            xiazaipanduan=true;
            progressDialog = new ProgressDialog(App.context);    //进度条,在下载的时候实时更新进度,提高用户友好度
            progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            progressDialog.setTitle("正在下载");
            progressDialog.setMessage("请稍候...");
            progressDialog.setProgress(0);
            //点击意外不消失
            progressDialog.setCanceledOnTouchOutside(false);
            //这是取消后即使下载完成也不安装,取消网络请求
            progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "取消",
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            progressDialog.dismiss();
                            xiazaipanduan=false;
                            okHttpClient.newCall(request).cancel();
                        }
                    });
            progressDialog.show();
            okHttpClient.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    App.context.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            callback.onError(110, "请求失败,下载失败");
                        }
                    });
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    InputStream is = null;//输入流
                    FileOutputStream fos = null;//输出流
                    try {
                        is = response.body().byteStream();//获取输入流
                        long total = response.body().contentLength();//获取文件大小
                        Log.e("下载文件长度为", total + "");
                        setMax(total);//为progressDialog设置大小
                        if (is != null) {
                            Log.d("下载数据", "onResponse: 不为空");
                            File file = new File(Environment.getExternalStorageDirectory(), "qianyan.apk");// 设置路径
                            fos = new FileOutputStream(file);
                            byte[] buf = new byte[1024];
                            int ch = -1;
                            int process = 0;
                            while ((ch = is.read(buf)) != -1) {
                                fos.write(buf, 0, ch);
                                process += ch;
                                downLoading(process);       //这里就是关键的实时更新进度了!
                            }

                        }
                        fos.flush();
                        // 下载完成
                        if (fos != null) {
                            fos.close();
                        }
//                    downSuccess();
                        App.context.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                if (progressDialog != null && progressDialog.isShowing()) {
                                    progressDialog.dismiss();
                                }
                                if(xiazaipanduan){
                                    callback.onSuccess("下载完成");
                                }
                            }
                        });
                    } catch (Exception e) {
                        downFial();
                        Log.d("SettingPresenter", e.toString());
                    } finally {
                        try {
                            if (is != null)
                                is.close();
                        } catch (IOException e) {
                        }
                        try {
                            if (fos != null)
                                fos.close();
                        } catch (IOException e) {
                        }
                    }
                }
            });
        } else {
            Toast.makeText(App.context, "SD卡不可用,请插入SD卡", Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public void loadImage(String url, ImageView imageView) {
        Glide.with(App.context).load(url).into(imageView);
    }

    /**
     * 自动解析json至回调中的JavaBean
     *
     * @param jsonData
     * @param callBack
     * @param <T>
     * @return
     */
    private <T> T getGeneric(String jsonData, MyNetWorkCallback<T> callBack) {
        Gson gson = new Gson();
        //通过反射获取泛型的实例
        Type[] types = callBack.getClass().getGenericInterfaces();
        Type[] actualTypeArguments = ((ParameterizedType) types[0]).getActualTypeArguments();
        Type type = actualTypeArguments[0];
        String s = jsonData.substring(1, jsonData.length());
        T t = gson.fromJson(jsonData, type);
        return t;
    }

    //取消
    public void cancel(String url, Map<String, String> params) {
        FormBody.Builder builder = new FormBody.Builder();
        if (params != null && params.size() > 0) {
            Set<String> keys = params.keySet();
            for (String key : keys) {
                String value = params.get(key);
                builder.add(key, value);
            }
        }
        Request request = new Request.Builder().url(url).post(builder.build()).build();
        okHttpClient.newCall(request).cancel();
    }

    //显示更新错误
    public void showError(final String msg) {
        App.context.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(App.context, msg, Toast.LENGTH_SHORT).show();
            }
        });

    }

    /**
     * 进度条实时更新
     *
     * @param i
     */
    public void downLoading(final int i) {
        App.context.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                progressDialog.setProgress(i);
            }
        });
    }

    /**
     * 下载成功
     */
    public void downSuccess() {
        App.context.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (progressDialog != null && progressDialog.isShowing()) {
                    progressDialog.dismiss();
                }

                AlertDialog.Builder builder = new AlertDialog.Builder(App.context);
                builder.setIcon(android.R.drawable.ic_dialog_info);
                builder.setTitle("下载完成");
                builder.setMessage("是否安装");
                builder.setCancelable(false);
                builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Intent intent = new Intent(Intent.ACTION_VIEW);
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //aandroid N的权限问题
                            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                            Uri contentUri = FileProvider.getUriForFile(App.context, "com.example.myapplication.fileprovider", new File(Environment.getExternalStorageDirectory(), "qianyan.apk"));//注意修改
                            intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
                        } else {
                            intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "qianyan.apk")), "application/vnd.android.package-archive");
                            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        }
                        App.context.startActivity(intent);
                    }
                });
                builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                    }
                });
                builder.create().show();

            }
        });
    }

    /**
     * 下载失败
     */
    public void downFial() {
        App.context.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                progressDialog.cancel();
                Toast.makeText(App.context, "更新失败", Toast.LENGTH_LONG).show();
            }
        });
    }

    public void setMax(final long total) {
        App.context.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                progressDialog.setMax((int) total);
            }
        });
    }
}

你会发现很多问题哈红的什么的APP类得有吧()要不怎么检测更新呢:

public  class App extends Application {
    public static MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
    public static MainActivity context = null;

}

准备工作都完成了,别拖延大家时间了开始使用吧:表单请求:

private Map<String, String> map = new HashMap<>();
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
//很重要的一行,要不然你就空指针去吧
        App.context = this;

    }

随便写个方法看你心情吧:

map.put("currentLang", "2");
                OkHttpUtils.getInstance().post(ApiUrl.HTTP_LOG, map, new MyNetWorkCallback<写自己的Bean>() {
                    @Override
                    public void onSuccess(写自己的Bean s) {
//解析
                        Gson gson = new Gson();
//变成实体类了自己用吧,随便用已经在子线程了随便吐司。
                        写自己的Bean logBean = gson.fromJson(s, 写自己的Bean.class);
                        Toast.makeText(MainActivity.this, "登入成功", Toast.LENGTH_SHORT).show();

                    }

                    @Override
                    public void onError(int errorCode, String errorMsg) {
                        Toast.makeText(MainActivity.this, "请求失败", Toast.LENGTH_SHORT).show();
                    }
                });

 

要图片的吗?来了:

Map<String, String> map = new HashMap<>();
        map.put("accessToken", toKen);
OkHttpUtils.getInstance().sendMultipart(path, map, "imgData", 存放图片的集合listfiles)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.newThread())
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable throwable) {
                        dialog.dismiss();
                        Toast.makeText(ComputerRoomPatrolavtivity.this, "上传失败了", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onNext(String s) {
                        s = s.trim();
                        s = s.substring(1, s.length() - 1);//去除首尾双引号。
                        String str = s.replace("\\", "");//去除所有的\
                        Gson gson = new Gson();
                        Log.e("TAG", "str=" + str);
                            ToastShow.show(ComputerRoomPatrolavtivity.this, "上传成功");
                        } else {
                            dialog.dismiss();
                            ToastShow.show(ComputerRoomPatrolavtivity.this, "失败" + bean.getErrorMessage());
                        }
                    }
                });

 

友情提示一下,我的张片上传之前都压缩了,这样上传比较爽。我用的是鲁班压缩可能很旧了凑合看吧

implementation 'top.zibin:Luban:1.1.3'
Luban.get(this)
                .load(file)                     //传人要压缩的图片
                .putGear(Luban.THIRD_GEAR)      //设定压缩档次,默认三挡
                .setCompressListener(new OnCompressListener() { //设置回调

                    @Override
                    public void onStart() {
                        // TODO 压缩开始前调用,可以在方法内启动 loading UI
                    }

                    @Override
                    public void onSuccess(File file) {
                        // TODO 压缩成功后调用,返回压缩后的图片文件
                        listFileImages.add(file);
                            //网络请求
                            httpssa(listFileImages,toKen,dataId);
                    }

                    @Override
                    public void onError(Throwable e) {
                        // TODO 当压缩过去出现问题时调用
                    }
                }).launch(); 

raw上传实战使用案例:

//和map同理。和添加map一样,因为我这边约定的是健值对的json传的串。
//为什么不用form-data,问后台把我也不清楚,咱们移动端请求就完了。
JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("userName","用户名");
            jsonObject.put("passWord","密码");
        } catch (JSONException e) {
            e.printStackTrace();
            Toast.makeText(MainActivity.this, "数据加入失败转型json", Toast.LENGTH_SHORT).show();
        }
        String postBody=jsonObject.toString();
        OkHttpUtils.getInstance().postraw(url, postBody, new MyNetWorkCallback<String>() {
            @Override
            public void onSuccess(String s) {
                    Toast.makeText(MainActivity.this, "登入成功", Toast.LENGTH_SHORT).show();
                }else{
                    Toast.makeText(MainActivity.this, "登入失败请从新登入", Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onError(int errorCode, String errorMsg) {
                Toast.makeText(MainActivity.this, "请求失败", Toast.LENGTH_SHORT).show();
            }
        });

软件更新配置文件:androidmanifest文件下配置:注意在application里

<provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="对应的包名.fileprovider"
            android:grantUriPermissions="true"
            android:exported="false"
            >
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

然后在res中创建xml包,存放file_paths.xml文件:

<paths>
    <external-path path="Android/data/com.earn/" name="files_root" />
    <external-path path="." name="external_storage_root" />
</paths>

注意:在跳转到安装界面时,android 6.0即android N以上的需要设置权限。

if (Build.VERSION.SDK_INT >= 23) {
            int REQUEST_CODE_CONTACT = 101;
            String[] permissions = {
                    Manifest.permission.WRITE_EXTERNAL_STORAGE};
            //验证是否许可权限
            for (String str : permissions) {
                if (MainActivity.this.checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) {
                    //申请权限
                    MainActivity.this.requestPermissions(permissions, REQUEST_CODE_CONTACT);
                    return;
                } else {
                    //这里就是权限打开之后自己要操作的逻辑
                }
            }
        }

//还有就是不用上面的:用下面的;基本上你要的权限都差不多申请了。可以根据需求删除或者添加。
boolean isGranted = true;
        if (android.os.Build.VERSION.SDK_INT >= 23) {
            if (MainActivity.this.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_DENIED) {
                //如果没有写sd卡权限
                isGranted = false;
            }
            if (MainActivity.this.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                isGranted = false;
            }
            if (MainActivity.this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) !=PackageManager.PERMISSION_GRANTED) {
                isGranted = false;
            }
            if (MainActivity.this.checkSelfPermission(Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                isGranted = false;
            }
            if (!isGranted) {
                MainActivity.this.requestPermissions(
                        new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission
                                .ACCESS_FINE_LOCATION,
                                Manifest.permission.READ_EXTERNAL_STORAGE,
                                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                                Manifest.permission.READ_PHONE_STATE,
                                Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS,
                                Manifest.permission.VIBRATE,
                                Manifest.permission.RECORD_AUDIO,
                                Manifest.permission.CALL_PHONE,
                                Manifest.permission.CAMERA},
                        102);
            }
        }

然后在做更新的时候,我测试用的是华为手机还是遇到问题了, 文件包名冲突,后来发现华为手机需要app内部安装权限,不知道别的手机是不是。所以上代码:

//建议放在下载之前,因为有的时候都不让下载最好在判断版本里面添加这个
//新的api
@RequiresApi(api = Build.VERSION_CODES.O)
boolean haveInstallPermission = mContext.getPackageManager().canRequestPackageInstalls();
 if(!haveInstallPermission){
   //权限没有打开则提示用户去手动打开
Uri packageURI = Uri.parse("package:" + getPackageName());
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI);
                    startActivityForResult(intent, 100);
 }
@Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode==100){
            Toast.makeText(MainActivity.this, "开启权限成功", Toast.LENGTH_LONG).show();
            //开启权限以后做的操作,下载更新安装。
OkHttpUtils.getInstance().download(urls, new MyNetWorkCallback<String>() {
                        @Override
                        public void onSuccess(String s) {
                            if(s.equals("下载完成")){
                                downSuccess();
                            }
                        }

                        @Override
                        public void onError(int errorCode, String errorMsg) {
                            Toast.makeText(MainActivity.this, errorMsg, Toast.LENGTH_SHORT).show();
                        }
                    });
        }
    }
/**
     * 下载成功
     */
public void downSuccess() {
        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        builder.setIcon(android.R.drawable.ic_dialog_info);
        builder.setTitle("下载完成");
        builder.setMessage("是否安装");
        builder.setCancelable(false);
        builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Intent intent = new Intent(Intent.ACTION_VIEW);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //aandroid N的权限问题
                    intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    Uri contentUri = FileProvider.getUriForFile(MainActivity.this, "com.example.ceshijk.provider", new File(Environment.getExternalStorageDirectory(), "ceshi.apk"));//注意修改
                    intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
                } else {
                    intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "ceshi.apk")), "application/vnd.android.package-archive");
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                }
                startActivity(intent);
            }
        });
        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
            }
        });
        builder.create().show();
    }

    

更新就完事了,亲测好使成功,有问题留言就好,看到必回。

目前的项目还没有涉及到长传图片,等涉及到了我自己用了我在改进,

在友情提示rxjava当中的长传图片观察者模式可能有些更改,自己看下最新的吧,然后调用,应该旧可以了,用不好的话的等我更新吧。

感谢新手借鉴,大佬指点。


版权声明:本文为q992767879原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。