【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+"\n";
            }
        } 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM