最近在寫一個雲備份功能,參考了一下市面上的軟件,發現有一種采用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