• 【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

  • 相关阅读:
    ADB命令大全
    Backup your Android without root or custom recovery -- adb backup
    Content portal for Pocketables Tasker articles
    Is there a way to detect if call is in progress? Phone Event
    Tasker to proximity screen off
    Tasker to detect application running in background
    Tasker to create toggle widget for ES ftp service -- Send Intent
    Tasker to proximity screen on
    Tasker to answer incoming call by pressing power button
    Tasker to stop Poweramp control for the headset while there is an incoming SMS
  • 原文地址:https://www.cnblogs.com/robotpaul/p/12005045.html
Copyright © 2020-2023  润新知