【Kotlin】Android-使用WebDAV协议云存储文件(详细)—附demo源码
Kotlin-Andriod使用WebDAV协议快速简单存储文件至云端(详细介绍),基于国内坚果云,免费好用,附demo源码
·
比起云服务器、云数据库、云存储等等方式将文件存储至云端,网盘的WebDAV协议对新手就友好的多,不仅仅有免部署、使用方式简单等等原因,更重要是免费,国内首推坚果云网盘!
三个注意点:
- 使用第三方库Sardine进行操作
- 添加网络访问权限
- 子线程进行云端请求
特别说明:
本文采用分—总结构展示代码(除gradle文件),即先展示局部代码,并说明其用法和作用;小节结尾处再给出该部分对应文件的完整代码。布局XML源文件在文末。
一、添加依赖
在gradle(Moudle)中添加第三方库Sardine所需依赖。
// 添加sardine库来使用WebDAV协议
implementation 'com.thegrizzlylabs.sardine-android:sardine-android:0.8'
implementation("com.squareup.okhttp3:okhttp:4.9.0")
二、声明网络权限
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.demo_webdav">
// 额外添加网络权限
<uses-permission android:name="android.permission.INTERNET" />
<application
...
</application>
</manifest>
三、创建操作网盘的方法
Sardine操作WebDAV协议的常用方法请参考常用方法一览
3.1初始化连接,返回一个可共用的Sardine对象
// 与坚果云WebDAV服务器建立连接,返回sardine对象以进行操作
fun initSardine(): OkHttpSardine {
val sardine = OkHttpSardine()
// 此处的账号和第三方密码口令均请填入自己的
// 坚果云的账号
val userName = "demo_webdav@163.com"
// 授权给第三方应用的密码口令
val passWord = "aqkgubiy4z55rc6p"
// 建立连接
sardine.setCredentials(userName, passWord)
// 返回sardine对象
return sardine
}
在坚果云生成第三方应用密码口令的方式请参考坚果云官方文档
3.2新建文件夹/目录至云端
fun createDir(sardine: OkHttpSardine) {
val dirPath = "https://dav.jianguoyun.com/dav/我的坚果云/demo_webdav文件夹"
sardine.createDirectory(dirPath)
}
3.3检查云端文件存在性
fun checkExistence(sardine: OkHttpSardine): Boolean {
val dirPath = "https://dav.jianguoyun.com/dav/我的坚果云/demo_webdav文件夹"
return sardine.exists(dirPath)
}
3.4上传文件至云端:将String变量转换为byte字节数组上传至网盘
fun uploadFile(sardine: OkHttpSardine, fileContent: String) {
val filePath = "https://dav.jianguoyun.com/dav/我的坚果云/demo_webdav文件夹/测试文本.txt"
// 将变量转变为byte字节数组,以传输到网盘
val data = fileContent.toByteArray()
sardine.put(filePath, data)
}
3.5下载云端文件方法:以输入流的形式读取,并转换为String变量存储
fun downloadFile(sardine: OkHttpSardine): String {
val filePath = "https://dav.jianguoyun.com/dav/我的坚果云/demo_webdav文件夹/测试文本.txt"
val download = sardine.get(filePath)
// 以输入流的形式读取下载的文件,并转换为字符串
val fileContent = BufferedReader(InputStreamReader(download)).useLines { lines ->
val results = StringBuilder()
lines.forEach {
results.append(it)
}
results.toString()
}
return fileContent
}
3.6重命名或移动文件(夹)的方法:
fun moveOrRenameFile(sardine: OkHttpSardine) {
val oldPath = "https://dav.jianguoyun.com/dav/我的坚果云/demo_webdav文件夹"
val newPath = "https://dav.jianguoyun.com/dav/我的坚果云/renamed_or_moved_demo_webdav文件夹"
sardine.move(oldPath, newPath)
}
3.7删除云端文件(夹)方法:
fun deleteFile(sardine: OkHttpSardine) {
val filePath = "https://dav.jianguoyun.com/dav/我的坚果云/moved_demo_webdav文件夹"
sardine.delete(filePath)
}
四、MainActivity中调用
4.1布局预览
4.2绑定视图控件
val show = findViewById<TextView>(R.id.show)
val createButton = findViewById<Button>(R.id.create)
val uploadButton = findViewById<Button>(R.id.upload)
val downloadButton = findViewById<Button>(R.id.download)
val renameButton = findViewById<Button>(R.id.rename)
val deleteButton = findViewById<Button>(R.id.delete)
4.3设置点击事件及真机测试
注:与网络请求有关的函数,需要放到子线程中进行!
// 启动一个子线程
thread {
// 在这内部写真正实现功能的函数
}
1.创建文件夹按钮
createButton.setOnClickListener {
// 启动子线程
thread {
// 连接到坚果云WebDAV服务器,并返回sardine对象
val sardine = initSardine()
// 文件夹不存在则创建一个
if (!checkExistence(sardine)) {
createDir(sardine)
}
}
}
2.上传文件按钮
uploadButton.setOnClickListener {
// 启动子线程
thread {
val sardine = initSardine()
uploadFile(sardine, "demo_webdav的测试文本,这将生成为一个txt文本存在WebDAV服务器端")
}
// Toast一下提醒已上传
Toast.makeText(this, "已上传", Toast.LENGTH_SHORT).show()
}
3.下载文件按钮
downloadButton.setOnClickListener {
var fileContent = ""
// 启动子线程
thread {
val sardine = initSardine()
fileContent = downloadFile(sardine)
}.join() // 阻塞子线程,以取得fileContent的值
// 将fileContent的值赋予show文本控件显示出来
show.text = fileContent
}
4.(移动)重命名文件夹按钮
renameButton.setOnClickListener {
// 启动子线程
thread {
val sardine = initSardine()
moveOrRenameFile(sardine)
}
// Toast一下提醒已重命名
Toast.makeText(this, "已重命名", Toast.LENGTH_SHORT).show()
}
5.删除文件夹按钮
deleteButton.setOnClickListener {
// 启动子线程
thread {
val sardine = initSardine()
deleteFile(sardine)
}
// Toast一下提醒已删除
Toast.makeText(this, "已删除", Toast.LENGTH_SHORT).show()
}
MainActivity完整代码
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 绑定视图控件
val show = findViewById<TextView>(R.id.show)
val createButton = findViewById<Button>(R.id.create)
val uploadButton = findViewById<Button>(R.id.upload)
val downloadButton = findViewById<Button>(R.id.download)
val renameButton = findViewById<Button>(R.id.rename)
val deleteButton = findViewById<Button>(R.id.delete)
// 设置创建文件夹按钮的点击事件
createButton.setOnClickListener {
// 启动子线程
thread {
// 连接到坚果云WebDAV服务器,并返回sardine对象
val sardine = initSardine()
// 文件夹不存在则创建一个
if (!checkExistence(sardine)) {
createDir(sardine)
}
}
}
// 设置上传文件按钮的点击事件
uploadButton.setOnClickListener {
// 启动子线程
thread {
val sardine = initSardine()
uploadFile(sardine, "demo_webdav的测试文本,这将生成为一个txt文本存在WebDAV服务器端")
}
// Toast一下提醒已上传
Toast.makeText(this, "已上传", Toast.LENGTH_SHORT).show()
}
// 设置下载文件按钮的点击事件
downloadButton.setOnClickListener {
var fileContent = ""
// 启动子线程
thread {
val sardine = initSardine()
fileContent = downloadFile(sardine)
}.join() // 阻塞子线程,以取得fileContent的值
// 将fileContent的值赋予show文本控件显示出来
show.text = fileContent
}
// 设置重命名文件夹按钮的点击事件
renameButton.setOnClickListener {
// 启动子线程
thread {
val sardine = initSardine()
moveOrRenameFile(sardine)
}
// Toast一下提醒已重命名
Toast.makeText(this, "已重命名", Toast.LENGTH_SHORT).show()
}
// 设置删除文件夹按钮的点击事件
deleteButton.setOnClickListener {
// 启动子线程
thread {
val sardine = initSardine()
deleteFile(sardine)
}
// Toast一下提醒已删除
Toast.makeText(this, "已删除", Toast.LENGTH_SHORT).show()
}
}
// 与坚果云WebDAV服务器建立连接,返回sardine对象以进行操作
fun initSardine(): OkHttpSardine {
val sardine = OkHttpSardine()
// 坚果云的账号邮箱
val userName = "demo_webdav@163.com"
// 授权给第三方应用的密码口令
val passWord = "aqkgubiy4z55rc6p"
// 建立连接
sardine.setCredentials(userName, passWord)
// 返回sardine对象
return sardine
}
fun createDir(sardine: OkHttpSardine) {
val dirPath = "https://dav.jianguoyun.com/dav/我的坚果云/demo_webdav文件夹"
sardine.createDirectory(dirPath)
}
fun checkExistence(sardine: OkHttpSardine): Boolean {
val dirPath = "https://dav.jianguoyun.com/dav/我的坚果云/demo_webdav文件夹"
return sardine.exists(dirPath)
}
fun uploadFile(sardine: OkHttpSardine, fileContent: String) {
val filePath = "https://dav.jianguoyun.com/dav/我的坚果云/demo_webdav文件夹/测试文本.txt"
// 将变量转变为byte字节数组,以传输到网盘
val data = fileContent.toByteArray()
sardine.put(filePath, data)
}
fun downloadFile(sardine: OkHttpSardine): String {
val filePath = "https://dav.jianguoyun.com/dav/我的坚果云/demo_webdav文件夹/测试文本.txt"
val download = sardine.get(filePath)
// 以文件流的形式读取下载的文件,并转换为字符串
val fileContent = BufferedReader(InputStreamReader(download)).useLines { lines ->
val results = StringBuilder()
lines.forEach {
results.append(it)
}
results.toString()
}
return fileContent
}
fun moveOrRenameFile(sardine: OkHttpSardine) {
val oldPath = "https://dav.jianguoyun.com/dav/我的坚果云/demo_webdav文件夹"
val newPath = "https://dav.jianguoyun.com/dav/我的坚果云/renamed_or_moved_demo_webdav文件夹"
sardine.move(oldPath, newPath)
}
fun deleteFile(sardine: OkHttpSardine) {
val filePath = "https://dav.jianguoyun.com/dav/我的坚果云/renamed_or_moved_demo_webdav文件夹"
sardine.delete(filePath)
}
}
布局XML完整代码
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.39" />
<Button
android:id="@+id/create"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:text="创建文件夹"
app:layout_constraintBottom_toTopOf="@+id/upload"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/show" />
<Button
android:id="@+id/upload"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="上传文件"
app:layout_constraintBottom_toTopOf="@+id/download"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/create" />
<Button
android:id="@+id/download"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="下载文件"
app:layout_constraintBottom_toTopOf="@+id/rename"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/upload" />
<Button
android:id="@+id/rename"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="重命名文件夹"
app:layout_constraintBottom_toTopOf="@+id/delete"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/download" />
<Button
android:id="@+id/delete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="删除文件夹"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/rename" />
</androidx.constraintlayout.widget.ConstraintLayout>
如有疏忽遗漏之处,敬请指出
本文demo源码 github、gitee地址:
更多推荐
已为社区贡献2条内容
所有评论(0)