zoukankan      html  css  js  c++  java
  • 【Android】WebDav For Android

    最近在写一个云备份功能,参考了一下市面上的软件,发现有一种采用WebDav协议的云备份成本比较低,故特地研究一下使用。

    服务器提供商是使用国内的坚果云,还是非常良心的。

    坚果云官网:https://www.jianguoyun.com

    注册账号后,点击账户信息,安全选项中即可看到 第三方应用管理

    这里需要三个东西,服务器地址、账户、密码(这个密码是你为应用单独开辟的,不是用户密码),具体参考:http://help.jianguoyun.com/?tag=webdav

    拿到数据后,我们就可以开始进行安卓开发了。

    依赖以及权限设置

     因为涉及到网络,所以需要在Manifests中设置联网权限:

     <uses-permission android:name="android.permission.INTERNET" /> 

    同时注意安卓9.0以上的网络安全策略,需要单独配置一下:

    在res新建一个 network_config.xml

    <?xml version="1.0" encoding="utf-8"?>
    <network-security-config>
        <base-config cleartextTrafficPermitted="true" />
    </network-security-config>

    接着在Manifests的application中配置:

    android:networkSecurityConfig="@xml/network__config"

    webDav网上的教程不是特别多,一开始找到的是 lookfirst/sardine

    该项目是使用的HttpClient且和安卓部分依赖有些冲突,所以不推荐直接使用

    后来在github中找到一个移植到安卓的sardine,项目地址

    经过测试可以直接使用。

    implementation 'com.thegrizzlylabs.sardine-android:sardine-android:0.5'

    当然你也可以直接翻到文末查看我提供的对sardine的二次封装库,使用起来更方便。

    基础使用方法

    请注意:以下所有方法都必须在新线程中进行,且对UI的直接操作要放回主线程进行,可以考虑使用Handler

    初始化

     Sardine sardine= new OkHttpSardine();
     sardine.setCredentials(userName,password);

    这里的userName,password即你的用户账号+分配的应用的所属密码

    获取目录下所有文件

    List<DavResource> resources = null;
            try {
                resources = sardine.list("https://dav.jianguoyun.com/dav/");//如果是目录一定别忘记在后面加上一个斜杠
                for (DavResource res : resources)
                {
                    listNames=listNames+res+"
    ";
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

    判断路径(或文件)是否存在

    //判断文件是否存在
    if (sardine.exists("https://dav.jianguoyun.com/dav/file1.jpg"))
        System.out.println("got here!");
    //判断路径是否存在
    if (sardine.exists("https://dav.jianguoyun.com/dav/file/"))
        System.out.println("got here!");

     若目录不存在,可以自己创建:

    sardine.createDirectory("https://dav.jianguoyun.com/dav/
    目录名称/");

    下载文件

    InputStream is = sardine.get("https://dav.jianguoyun.com/dav/"+"文件目录"+"afile.jpg");

    上传文件

    byte[] data = FileUtils.readFileToByteArray(new File("/file/on/disk"));
    sardine.put("http://yourdavserver.com/adirectory/nameOfFile.jpg", data);

    或者使用

    InputStream fis = new FileInputStream(new File("/some/file/on/disk.txt"));
    sardine.put("http://yourdavserver.com/adirectory/nameOfFile.jpg", fis);

    节省内存空间

    删除文件

    sardine.delete("http://yourdavserver.com/adirectory/nameOfFile.jpg");

    综合例子

    这里给出一个简单的例子,可以把这些代码统一封装成一个类

    /**
     * 同步管理器
     * SyncManager(Context context)
     * getCloudFiles(final Handler handler) 获取文件
     * public void upDate(final Handler handler) 更新文件
     * */
    public class SyncManager {
        private String serverHostUrl;//WebDav服务器地址,坚果云为:https://dav.jianguoyun.com/dav/
        private String userName;//用户名
        private String password;//密码
        private Sardine sardine;
        private Context context;
        private SettingManager settingManager;
    
        public SyncManager(Context context){
            this.context=context;
            //初始化设置,主要是获取用户设定的服务器地址、用户名和密码
            settingManager=new SettingManager(context);
            serverHostUrl=settingManager.getUserServer();
            userName=settingManager.getUsername();
            password=settingManager.getPassword();
            //初始化sardine,使用OkHttpSardine进行实例化
            sardine=new OkHttpSardine();
        }
        /**
         * 更新数据(即上传数据)
         * @param counterEvents 数据源
         * @param handler 线程回调
         * */
        private void updateFiles(List<CounterEvent> counterEvents,Handler handler){
            sardine.setCredentials(userName,password);//设置登录账号,登录
            //自己规定一种数据格式,这里面我采用的是json
            Gson gson=new Gson();
            String jsons=gson.toJson(counterEvents);
            //把要上传的数据转成byte数组
            byte[] data=jsons.getBytes();
            try {
                //首先判断目标存储路径文件夹存不存在
                if(!sardine.exists(serverHostUrl+"pickTime/")){
                    //若不存在需要创建目录
                    sardine.createDirectory(serverHostUrl+"pickTime/");
                }
                //存入数据
                sardine.put(serverHostUrl+"pickTime/backup.txt",data);
                //通知主线程进行下一步操作
                Message message=new Message();
                message.what=1;
                handler.sendMessage(message);
            } catch (IOException e) {
                Message message=new Message();
                message.what=-1;
                message.obj=e;
                handler.sendMessage(message);
                Log.d("啥情况",e.toString());
                e.printStackTrace();
            }
        }
        /**
         * 封装的更新方法
         * @param handler 回调
         * */
        public void upDate(final Handler handler){
            if(userName.equals("")||password.equals("")){
                Toasty.info(context,"请设置账号",Toasty.LENGTH_SHORT).show();
                Intent intent=new Intent(context, SettingActivity.class);
                context.startActivity(intent);
            }else {
                //开启线程进行执行操作
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        updateFiles(Manager.getAllCounterEvents(context),handler);
                    }
                }).start();
            }
        }
        /**
         * 封装的获取文件方法
         * @param handler 回调
         * */
        public void getCloudFiles(final Handler handler){
            if(userName.equals("")||password.equals("")){
                Toasty.info(context,"请设置账号",Toasty.LENGTH_SHORT).show();
                Intent intent=new Intent(context, SettingActivity.class);
                context.startActivity(intent);
            }else {
                Toasty.info(context,"恢复中",Toasty.LENGTH_SHORT).show();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        getFiles(handler);
                    }
                }).start();
            }
        }
        /**
         * 获取文件
         * @param handler 回调
         * */
        private void getFiles(Handler handler){
            sardine.setCredentials(userName,password);//登录。设置账号
            try {
                //拿到输入流
                InputStream inputStream=sardine.get(serverHostUrl+"pickTime/backup.txt");
                //设置输入缓冲区
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); // 实例化输入流,并获取网页代
                String s; // 依次循环,至到读的值为空
                StringBuilder sb = new StringBuilder();
                while ((s = reader.readLine()) != null) {
                    sb.append(s);
                }
                reader.close();
    
                String str = sb.toString();
                //TODO 这里放你的处理逻辑,或者由handler传送给相应处理
                Message message=new Message();
                message.what=2;
                handler.sendMessage(message);
            } catch (IOException e) {
                Message message=new Message();
                message.what=-2;
                message.obj=e;
                handler.sendMessage(message);
                e.printStackTrace();
            }
    
        }
    
    }

    封装库

    我已经把该代码封装成了一个库,可以直接使用:https://github.com/paul623/WebDavSyncerDemo

    implementation 'com.paul623.wdsyncer:wdsyncer:0.0.1'

    具体功能及实现请查看github

  • 相关阅读:
    SQL注入原理解说,非常不错!
    Asp.Netserver控件开发的Grid实现(三)列编辑器
    Windows下搭建deepnet环境
    reactor设计模式
    C++ 表达式语句 海伦的故事
    [ArcGIS必打补丁]ArcGIS 10.1 SP1 for (Desktop, Engine, Server) Quality Improvement Patch
    四个好看的CSS样式表格
    UVA 10047 The Monocycle (状态记录广搜)
    二叉搜索树相关性质的应用
    广播(broadcast)、电视与电视网络
  • 原文地址:https://www.cnblogs.com/robotpaul/p/12005045.html
Copyright © 2011-2022 走看看