新增ftp上传拦截器 https://github.com/AriaLyy/Aria/issues/402
This commit is contained in:
@@ -37,6 +37,7 @@ import com.arialyy.aria.exception.BaseException;
|
||||
import com.arialyy.aria.exception.FileNotFoundException;
|
||||
import com.arialyy.aria.exception.TaskException;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import com.arialyy.aria.util.Regular;
|
||||
import com.arialyy.aria.util.SSLContextUtil;
|
||||
|
||||
@@ -96,8 +97,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
|
||||
ALog.e(TAG, String.format("任务【%s】失败", mTaskDelegate.getUrlEntity().url));
|
||||
return;
|
||||
}
|
||||
String remotePath =
|
||||
new String(getRemotePath().getBytes(charSet), AbsFtpThreadTask.SERVER_CHARSET);
|
||||
String remotePath = CommonUtil.convertFtpChar(charSet, getRemotePath());
|
||||
if (mTaskDelegate.getUrlEntity().isFtps) {
|
||||
((FTPSClient) client).execPROT("P");
|
||||
//((FTPSClient) client).enterLocalActiveMode();
|
||||
@@ -123,7 +123,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
|
||||
} else {
|
||||
ALog.w(TAG, String.format("获取文件列表失败,msg:%s", client.getReplyString()));
|
||||
}
|
||||
client.disconnect();
|
||||
closeClient(client);
|
||||
|
||||
failDownload(new FileNotFoundException(TAG,
|
||||
String.format("文件不存在,url: %s, remotePath:%s", mTaskDelegate.getUrlEntity().url,
|
||||
@@ -133,8 +133,8 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
|
||||
|
||||
// 处理拦截功能
|
||||
if (!onInterceptor(client, files)) {
|
||||
client.disconnect();
|
||||
failDownload(new AriaIOException(TAG, "拦截器处理任务失败"), false);
|
||||
closeClient(client);
|
||||
ALog.d(TAG, "拦截器处理完成任务,任务将不再执行");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
|
||||
//服务器上没有该文件路径,表示该任务为新的上传任务
|
||||
mTaskWrapper.setNewTask(true);
|
||||
} else {
|
||||
client.disconnect();
|
||||
closeClient(client);
|
||||
failDownload(new AriaIOException(TAG,
|
||||
String.format("获取文件信息错误,url: %s, errorCode:%s, errorMsg:%s",
|
||||
mTaskDelegate.getUrlEntity().url, reply, client.getReplyString())), true);
|
||||
@@ -172,7 +172,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
|
||||
* 处理拦截
|
||||
*
|
||||
* @param ftpFiles remotePath路径下的所有文件
|
||||
* @return {@code false} 拦截器处理任务失败,{@code} 拦截器处理任务成功
|
||||
* @return {@code false} 拦截器处理完成任务,任务将不再执行,{@code true} 拦截器处理任务完成任务,任务继续执行
|
||||
*/
|
||||
protected boolean onInterceptor(FTPClient client, FTPFile[] ftpFiles) {
|
||||
return true;
|
||||
@@ -293,7 +293,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
|
||||
return client;
|
||||
}
|
||||
|
||||
private void closeClient(FTPClient client) {
|
||||
protected void closeClient(FTPClient client) {
|
||||
try {
|
||||
if (client != null && client.isConnected()) {
|
||||
client.disconnect();
|
||||
@@ -372,8 +372,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
|
||||
ALog.d(TAG, "isValid = " + file.isValid());
|
||||
handleFile(path + file.getName(), file);
|
||||
} else {
|
||||
String remotePath =
|
||||
new String((path + file.getName()).getBytes(charSet), AbsFtpThreadTask.SERVER_CHARSET);
|
||||
String remotePath = CommonUtil.convertFtpChar(charSet, path + file.getName());
|
||||
size += getFileSize(client.listFiles(remotePath), client, path + file.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,10 +42,6 @@ public abstract class AbsFtpThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTI
|
||||
extends AbsThreadTask<ENTITY, TASK_ENTITY> {
|
||||
private final String TAG = "AbsFtpThreadTask";
|
||||
protected String charSet;
|
||||
/**
|
||||
* D_FTP 服务器编码
|
||||
*/
|
||||
public static String SERVER_CHARSET = "ISO-8859-1";
|
||||
|
||||
protected AbsFtpThreadTask(StateConstance constance, IEventListener listener,
|
||||
SubThreadConfig<TASK_ENTITY> info) {
|
||||
|
||||
@@ -18,7 +18,7 @@ package com.arialyy.aria.core.common.ftp;
|
||||
import android.text.TextUtils;
|
||||
|
||||
/**
|
||||
* Ftp上传拦截器处理
|
||||
* Ftp上传拦截器处理,只针对新任务有效
|
||||
*
|
||||
* 如果使用者同时实现{@link Builder#resetFileName(String)}和{@link Builder#coverServerFile},
|
||||
* 将默认使用{@link Builder#coverServerFile}
|
||||
@@ -29,8 +29,6 @@ public class FtpInterceptHandler {
|
||||
|
||||
private String newFileName;
|
||||
|
||||
private boolean stopUpload;
|
||||
|
||||
private FtpInterceptHandler() {
|
||||
}
|
||||
|
||||
@@ -42,10 +40,6 @@ public class FtpInterceptHandler {
|
||||
return newFileName;
|
||||
}
|
||||
|
||||
public boolean isStopUpload() {
|
||||
return stopUpload;
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private boolean coverServerFile = false;
|
||||
|
||||
@@ -87,9 +81,7 @@ public class FtpInterceptHandler {
|
||||
*/
|
||||
public FtpInterceptHandler build() {
|
||||
FtpInterceptHandler handler = new FtpInterceptHandler();
|
||||
if (stopUpload) {
|
||||
handler.stopUpload = true;
|
||||
} else if (coverServerFile) {
|
||||
if (coverServerFile) {
|
||||
handler.coverServerFile = true;
|
||||
} else if (!TextUtils.isEmpty(newFileName)) {
|
||||
handler.newFileName = newFileName;
|
||||
|
||||
@@ -41,6 +41,19 @@ public class FtpTaskDelegate implements ITargetHeadDelegate {
|
||||
*/
|
||||
private IFtpUploadInterceptor uploadInterceptor;
|
||||
|
||||
/**
|
||||
* 上传到服务器文件的新文件名{@link FtpInterceptHandler#getNewFileName()}
|
||||
*/
|
||||
private String newFileName;
|
||||
|
||||
public String getNewFileName() {
|
||||
return newFileName;
|
||||
}
|
||||
|
||||
public void setNewFileName(String newFileName) {
|
||||
this.newFileName = newFileName;
|
||||
}
|
||||
|
||||
public IFtpUploadInterceptor getUploadInterceptor() {
|
||||
return uploadInterceptor;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.arialyy.aria.exception.AriaIOException;
|
||||
import com.arialyy.aria.exception.TaskException;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -84,8 +85,7 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
return this;
|
||||
}
|
||||
String remotePath =
|
||||
new String(getTaskWrapper().asFtp().getUrlEntity().remotePath.getBytes(charSet),
|
||||
SERVER_CHARSET);
|
||||
CommonUtil.convertFtpChar(charSet, getTaskWrapper().asFtp().getUrlEntity().remotePath);
|
||||
ALog.i(TAG, String.format("remotePath【%s】", remotePath));
|
||||
is = client.retrieveFileStream(remotePath);
|
||||
reply = client.getReplyCode();
|
||||
@@ -135,7 +135,8 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
return;
|
||||
}
|
||||
ALog.i(TAG,
|
||||
String.format("任务【%s】线程__%s__下载完毕", getConfig().TEMP_FILE.getName(), getConfig().THREAD_ID));
|
||||
String.format("任务【%s】线程__%s__下载完毕", getConfig().TEMP_FILE.getName(),
|
||||
getConfig().THREAD_ID));
|
||||
writeConfig(true, getConfig().END_LOCATION);
|
||||
getState().COMPLETE_THREAD_NUM++;
|
||||
if (getState().isComplete()) {
|
||||
@@ -143,7 +144,8 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
boolean success = mergeFile();
|
||||
if (!success) {
|
||||
mListener.onFail(false,
|
||||
new TaskException(TAG, String.format("任务【%s】分块文件合并失败", getConfig().TEMP_FILE.getName())));
|
||||
new TaskException(TAG,
|
||||
String.format("任务【%s】分块文件合并失败", getConfig().TEMP_FILE.getName())));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -216,7 +218,8 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
private void readNormal(InputStream is) {
|
||||
BufferedRandomAccessFile file = null;
|
||||
try {
|
||||
file = new BufferedRandomAccessFile(getConfig().TEMP_FILE, "rwd", getTaskConfig().getBuffSize());
|
||||
file =
|
||||
new BufferedRandomAccessFile(getConfig().TEMP_FILE, "rwd", getTaskConfig().getBuffSize());
|
||||
file.seek(getConfig().START_LOCATION);
|
||||
byte[] buffer = new byte[getTaskConfig().getBuffSize()];
|
||||
int len;
|
||||
|
||||
@@ -23,13 +23,12 @@ import com.arialyy.aria.core.common.CompleteInfo;
|
||||
import com.arialyy.aria.core.common.OnFileInfoCallback;
|
||||
import com.arialyy.aria.core.common.TaskRecord;
|
||||
import com.arialyy.aria.core.common.ThreadRecord;
|
||||
import com.arialyy.aria.core.common.ftp.AbsFtpThreadTask;
|
||||
import com.arialyy.aria.core.common.ftp.FtpInterceptHandler;
|
||||
import com.arialyy.aria.core.common.ftp.IFtpUploadInterceptor;
|
||||
import com.arialyy.aria.core.queue.UploadTaskQueue;
|
||||
import com.arialyy.aria.core.upload.UTaskWrapper;
|
||||
import com.arialyy.aria.core.upload.UploadEntity;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import com.arialyy.aria.util.DbDataHelper;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@@ -59,6 +58,10 @@ class FtpFileInfoThread extends AbsFtpInfoThread<UploadEntity, UTaskWrapper> {
|
||||
}
|
||||
|
||||
@Override protected boolean onInterceptor(FTPClient client, FTPFile[] ftpFiles) {
|
||||
// 旧任务将不做处理,否则断点续传上传将失效
|
||||
if (!mTaskWrapper.isNewTask()) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
IFtpUploadInterceptor interceptor = mTaskWrapper.asFtp().getUploadInterceptor();
|
||||
if (interceptor != null) {
|
||||
@@ -73,30 +76,26 @@ class FtpFileInfoThread extends AbsFtpInfoThread<UploadEntity, UTaskWrapper> {
|
||||
|
||||
FtpInterceptHandler interceptHandler = interceptor.onIntercept(mEntity, files);
|
||||
|
||||
if (interceptHandler.isStopUpload()) {
|
||||
// TODO: 2019-05-22 操作任务停止
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
处理远端有同名文件的情况
|
||||
*/
|
||||
if (files.contains(mEntity.getFileName())) {
|
||||
if (interceptHandler.isCoverServerFile()) {
|
||||
ALog.i(TAG, String.format("远端已拥有同名文件,将覆盖该文件,文件名:%s", mEntity.getFileName()));
|
||||
boolean b = client.deleteFile(
|
||||
new String(getRemotePath().getBytes(charSet), AbsFtpThreadTask.SERVER_CHARSET));
|
||||
boolean b = client.deleteFile(CommonUtil.convertFtpChar(charSet, getRemotePath()));
|
||||
ALog.d(TAG,
|
||||
String.format("删除文件%s,code: %s, msg: %s", b ? "成功" : "失败", client.getReplyCode(),
|
||||
client.getReplyString()));
|
||||
} else if (!TextUtils.isEmpty(interceptHandler.getNewFileName())) {
|
||||
ALog.i(TAG, String.format("远端已拥有同名文件,将修改remotePath,文件名:%s,remotePath:%s",
|
||||
ALog.i(TAG, String.format("远端已拥有同名文件,将修改remotePath,原文件名:%s,新文件名:%s",
|
||||
mEntity.getFileName(), interceptHandler.getNewFileName()));
|
||||
remotePath = mTaskWrapper.asFtp().getUrlEntity().remotePath
|
||||
+ "/"
|
||||
+ interceptHandler.getNewFileName();
|
||||
client.disconnect();
|
||||
mTaskWrapper.asFtp().setNewFileName(interceptHandler.getNewFileName());
|
||||
closeClient(client);
|
||||
run();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,14 @@
|
||||
*/
|
||||
package com.arialyy.aria.core.upload.uploader;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import aria.apache.commons.net.ftp.FTPClient;
|
||||
import aria.apache.commons.net.ftp.FTPReply;
|
||||
import aria.apache.commons.net.ftp.OnFtpInputStreamListener;
|
||||
import com.arialyy.aria.core.common.StateConstance;
|
||||
import com.arialyy.aria.core.common.SubThreadConfig;
|
||||
import com.arialyy.aria.core.common.ftp.AbsFtpThreadTask;
|
||||
import com.arialyy.aria.core.common.ftp.FtpTaskDelegate;
|
||||
import com.arialyy.aria.core.config.BaseTaskConfig;
|
||||
import com.arialyy.aria.core.config.DownloadConfig;
|
||||
import com.arialyy.aria.core.config.UploadConfig;
|
||||
@@ -31,6 +33,7 @@ import com.arialyy.aria.exception.AriaIOException;
|
||||
import com.arialyy.aria.exception.TaskException;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
@@ -82,7 +85,8 @@ class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UTaskWrapper> {
|
||||
return this;
|
||||
}
|
||||
|
||||
file = new BufferedRandomAccessFile(getConfig().TEMP_FILE, "rwd", getTaskConfig().getBuffSize());
|
||||
file =
|
||||
new BufferedRandomAccessFile(getConfig().TEMP_FILE, "rwd", getTaskConfig().getBuffSize());
|
||||
if (getConfig().START_LOCATION != 0) {
|
||||
//file.skipBytes((int) getConfig().START_LOCATION);
|
||||
file.seek(getConfig().START_LOCATION);
|
||||
@@ -92,7 +96,8 @@ class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UTaskWrapper> {
|
||||
return this;
|
||||
}
|
||||
ALog.i(TAG,
|
||||
String.format("任务【%s】线程__%s__上传完毕", getConfig().TEMP_FILE.getName(), getConfig().THREAD_ID));
|
||||
String.format("任务【%s】线程__%s__上传完毕", getConfig().TEMP_FILE.getName(),
|
||||
getConfig().THREAD_ID));
|
||||
writeConfig(true, getConfig().END_LOCATION);
|
||||
getState().COMPLETE_THREAD_NUM++;
|
||||
if (getState().isComplete()) {
|
||||
@@ -100,11 +105,13 @@ class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UTaskWrapper> {
|
||||
}
|
||||
if (getState().isFail()) {
|
||||
mListener.onFail(false, new TaskException(TAG,
|
||||
String.format("上传失败,filePath: %s, uploadUrl: %s", getEntity().getFilePath(), getConfig().URL)));
|
||||
String.format("上传失败,filePath: %s, uploadUrl: %s", getEntity().getFilePath(),
|
||||
getConfig().URL)));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
fail(mChildCurrentLocation, new AriaIOException(TAG,
|
||||
String.format("上传失败,filePath: %s, uploadUrl: %s", getEntity().getFilePath(), getConfig().URL)));
|
||||
String.format("上传失败,filePath: %s, uploadUrl: %s", getEntity().getFilePath(),
|
||||
getConfig().URL)));
|
||||
} catch (Exception e) {
|
||||
fail(mChildCurrentLocation, new AriaIOException(TAG, null, e));
|
||||
} finally {
|
||||
@@ -123,10 +130,17 @@ class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UTaskWrapper> {
|
||||
}
|
||||
|
||||
private void initPath() throws UnsupportedEncodingException {
|
||||
dir = new String(getTaskWrapper().asFtp().getUrlEntity().remotePath.getBytes(charSet),
|
||||
SERVER_CHARSET);
|
||||
remotePath = new String(String.format("%s/%s", getTaskWrapper().asFtp().getUrlEntity().remotePath,
|
||||
getEntity().getFileName()).getBytes(charSet), SERVER_CHARSET);
|
||||
FtpTaskDelegate delegate = getTaskWrapper().asFtp();
|
||||
dir = CommonUtil.convertFtpChar(charSet, delegate.getUrlEntity().remotePath);
|
||||
|
||||
String fileName =
|
||||
TextUtils.isEmpty(delegate.getNewFileName()) ? CommonUtil.convertFtpChar(charSet,
|
||||
getEntity().getFileName())
|
||||
: CommonUtil.convertFtpChar(charSet, delegate.getNewFileName());
|
||||
|
||||
remotePath =
|
||||
CommonUtil.convertFtpChar(charSet,
|
||||
String.format("%s/%s", delegate.getUrlEntity().remotePath, fileName));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -78,6 +78,19 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
public class CommonUtil {
|
||||
private static final String TAG = "CommonUtil";
|
||||
public static final String SERVER_CHARSET = "ISO-8859-1";
|
||||
|
||||
/**
|
||||
* 将字符串转换为Ftp服务器默认的ISO-8859-1编码
|
||||
*
|
||||
* @param charSet 原字符串编码s
|
||||
* @param str 需要转换的字符串
|
||||
* @return 转换后的字符串
|
||||
*/
|
||||
public static String convertFtpChar(String charSet, String str)
|
||||
throws UnsupportedEncodingException {
|
||||
return new String(str.getBytes(charSet), SERVER_CHARSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查分块任务是否存在
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
## 开发日志
|
||||
+ v_3.6.5
|
||||
- fix bug https://github.com/AriaLyy/Aria/issues/403
|
||||
- 新增ftp上传拦截器 https://github.com/AriaLyy/Aria/issues/402
|
||||
+ v_3.6.4 (2019/5/16)
|
||||
- 优化任务接收器的代码结构
|
||||
- 修复`DbEntity.saveAll()`失败的问题
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
<!--android:name=".test.TestFTPDirActivity"-->
|
||||
<!--android:name=".test.TestFTPActivity"-->
|
||||
<!--android:name=".download.group.DownloadGroupActivity"-->
|
||||
<!--android:name=".MainActivity"-->
|
||||
<!--android:name=".MainActivity"-->
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
@@ -44,6 +44,16 @@
|
||||
<activity android:name=".core.download.KotlinDownloadActivity"/>
|
||||
|
||||
<service android:name=".core.download.service_download.DownloadService"/>
|
||||
|
||||
<provider
|
||||
android:name="android.support.v4.content.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/aria_fileprovider_paths"/>
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.simple.common;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import com.arialyy.simple.R;
|
||||
import com.arialyy.simple.base.BaseDialog;
|
||||
import com.arialyy.simple.databinding.DialogModifyUrlBinding;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/3.
|
||||
*/
|
||||
@SuppressLint("ValidFragment") public class ModifyUrlDialog
|
||||
extends BaseDialog<DialogModifyUrlBinding> {
|
||||
public static final int MODIFY_URL_DIALOG_RESULT = 0xA1;
|
||||
|
||||
private String mTitle, mText;
|
||||
|
||||
public ModifyUrlDialog(Object obj, String title, String defaultText) {
|
||||
super(obj);
|
||||
mTitle = title;
|
||||
mText = defaultText;
|
||||
}
|
||||
|
||||
@Override protected void init(Bundle savedInstanceState) {
|
||||
super.init(savedInstanceState);
|
||||
getBinding().setTitle(mTitle);
|
||||
getBinding().setText(mText);
|
||||
getBinding().cancel.setOnClickListener(new View.OnClickListener() {
|
||||
@Override public void onClick(View v) {
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
getBinding().enter.setOnClickListener(new View.OnClickListener() {
|
||||
@Override public void onClick(View v) {
|
||||
getSimplerModule().onDialog(MODIFY_URL_DIALOG_RESULT, mText);
|
||||
}
|
||||
});
|
||||
getBinding().edit.post(new Runnable() {
|
||||
@Override public void run() {
|
||||
getBinding().edit.setSelection(mText.length());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override protected int setLayoutId() {
|
||||
return R.layout.dialog_modify_url;
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ import java.io.File;
|
||||
* Ftp下载测试
|
||||
*/
|
||||
public class FtpDownloadActivity extends BaseActivity<ActivityFtpDownloadBinding> {
|
||||
private final String URL = "sftp://9.9.9.205:2222/Cyberduck-6.9.4.30164.zip";
|
||||
private final String URL = "ftp://9.9.9.205:2121/Cyberduck-6.9.4.30164.zip";
|
||||
//private final String URL = "ftp://182.92.180.213:21/video/572fed5c2ad48_1024.jpg";
|
||||
//private final String URL = "ftp://182.92.180.213:21/DATA/20180205/rar/1111.rar";
|
||||
//private final String URL = "ftp://d:d@dygodj8.com:12311/咖啡风暴HD大陆公映意语中字[飘花www.piaohua.com].mp4";
|
||||
|
||||
@@ -15,7 +15,11 @@
|
||||
*/
|
||||
package com.arialyy.simple.core.upload;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.content.FileProvider;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import com.arialyy.annotations.Upload;
|
||||
@@ -27,8 +31,10 @@ import com.arialyy.aria.core.upload.UploadTask;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import com.arialyy.frame.util.FileUtil;
|
||||
import com.arialyy.frame.util.show.T;
|
||||
import com.arialyy.simple.BuildConfig;
|
||||
import com.arialyy.simple.R;
|
||||
import com.arialyy.simple.base.BaseActivity;
|
||||
import com.arialyy.simple.common.ModifyUrlDialog;
|
||||
import com.arialyy.simple.databinding.ActivityFtpUploadBinding;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
@@ -37,45 +43,81 @@ import java.util.List;
|
||||
* Created by lyy on 2017/7/28. Ftp 文件上传demo
|
||||
*/
|
||||
public class FtpUploadActivity extends BaseActivity<ActivityFtpUploadBinding> {
|
||||
private final String FILE_PATH = "/mnt/sdcard/AriaPrj.rar";
|
||||
private final String URL = "ftp://9.9.9.205:2121/aa/你好";
|
||||
private final int OPEN_FILE_MANAGER_CODE = 0xB1;
|
||||
private String mFilePath = "/mnt/sdcard/AriaPrj.rar";
|
||||
private String mUrl = "ftp://9.9.9.205:2121/aa/你好";
|
||||
|
||||
@Override protected void init(Bundle savedInstanceState) {
|
||||
setTile("D_FTP 文件上传");
|
||||
super.init(savedInstanceState);
|
||||
Aria.upload(this).register();
|
||||
UploadEntity entity = Aria.upload(this).getUploadEntity(FILE_PATH);
|
||||
UploadEntity entity = Aria.upload(this).getUploadEntity(mFilePath);
|
||||
if (entity != null) {
|
||||
getBinding().setFileSize(CommonUtil.formatFileSize(entity.getFileSize()));
|
||||
getBinding().setProgress(entity.isComplete() ? 100
|
||||
: (int) (entity.getCurrentProgress() * 100 / entity.getFileSize()));
|
||||
}
|
||||
getBinding().setUrl(mUrl);
|
||||
getBinding().setFilePath(mFilePath);
|
||||
getBinding().setViewModel(this);
|
||||
}
|
||||
|
||||
@Override protected int setLayoutId() {
|
||||
return R.layout.activity_ftp_upload;
|
||||
}
|
||||
|
||||
public void chooseUrl() {
|
||||
ModifyUrlDialog dialog =
|
||||
new ModifyUrlDialog(this, getString(R.string.modify_url_dialog_title), mUrl);
|
||||
dialog.show(getSupportFragmentManager(), "ModifyUrlDialog");
|
||||
}
|
||||
|
||||
public void chooseFilePath() {
|
||||
|
||||
File parentFile = new File(mFilePath);
|
||||
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
Uri uri;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
uri = FileProvider.getUriForFile(this,
|
||||
BuildConfig.APPLICATION_ID + ".provider",
|
||||
parentFile.getParentFile());
|
||||
} else {
|
||||
uri = Uri.fromFile(parentFile.getParentFile());
|
||||
}
|
||||
|
||||
intent.setDataAndType(uri, "*/*");
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
|
||||
startActivityForResult(intent, OPEN_FILE_MANAGER_CODE);
|
||||
}
|
||||
|
||||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.start:
|
||||
Aria.upload(this).loadFtp(FILE_PATH).setUploadUrl(URL).setUploadInterceptor(
|
||||
new IFtpUploadInterceptor() {
|
||||
if (Aria.upload(this).load(mFilePath).isRunning()) {
|
||||
Aria.upload(this).loadFtp(mFilePath).stop();
|
||||
getBinding().setStateStr(getString(R.string.resume));
|
||||
} else {
|
||||
getBinding().setStateStr(getString(R.string.stop));
|
||||
Aria.upload(this).loadFtp(mFilePath).setUploadUrl(mUrl).setUploadInterceptor(
|
||||
new IFtpUploadInterceptor() {
|
||||
|
||||
@Override
|
||||
public FtpInterceptHandler onIntercept(UploadEntity entity, List<String> fileList) {
|
||||
FtpInterceptHandler.Builder builder = new FtpInterceptHandler.Builder();
|
||||
builder.coverServerFile();
|
||||
//builder.resetFileName("test");
|
||||
return builder.build();
|
||||
}
|
||||
}).login("lao", "123456").start();
|
||||
break;
|
||||
case R.id.stop:
|
||||
Aria.upload(this).loadFtp(FILE_PATH).stop();
|
||||
@Override
|
||||
public FtpInterceptHandler onIntercept(UploadEntity entity, List<String> fileList) {
|
||||
FtpInterceptHandler.Builder builder = new FtpInterceptHandler.Builder();
|
||||
//builder.coverServerFile();
|
||||
builder.resetFileName("test.zip");
|
||||
return builder.build();
|
||||
}
|
||||
})
|
||||
//.login("lao", "123456")
|
||||
.login("N0rI", "0qcK")
|
||||
.start();
|
||||
}
|
||||
break;
|
||||
case R.id.cancel:
|
||||
Aria.upload(this).loadFtp(FILE_PATH).cancel();
|
||||
Aria.upload(this).loadFtp(mFilePath).cancel();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -123,4 +165,20 @@ public class FtpUploadActivity extends BaseActivity<ActivityFtpUploadBinding> {
|
||||
getBinding().setSpeed("");
|
||||
T.showShort(this, "文件:" + task.getEntity().getFileName() + ",上传完成");
|
||||
}
|
||||
|
||||
@Override protected void dataCallback(int result, Object data) {
|
||||
super.dataCallback(result, data);
|
||||
if (result == ModifyUrlDialog.MODIFY_URL_DIALOG_RESULT) {
|
||||
mUrl = String.valueOf(data);
|
||||
getBinding().setUrl(mUrl);
|
||||
}
|
||||
}
|
||||
|
||||
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == OPEN_FILE_MANAGER_CODE && resultCode == RESULT_OK) {
|
||||
Uri uri = data.getData();
|
||||
//Toast.makeText(this, "文件路径:" + uri.getPath(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
84
app/src/main/java/com/arialyy/simple/widget/SvgTextView.java
Normal file
84
app/src/main/java/com/arialyy/simple/widget/SvgTextView.java
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.simple.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.databinding.BindingAdapter;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.DrawableRes;
|
||||
import android.support.v7.widget.AppCompatImageView;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import com.arialyy.simple.R;
|
||||
|
||||
public class SvgTextView extends RelativeLayout {
|
||||
|
||||
private TextView textView;
|
||||
private AppCompatImageView icon;
|
||||
|
||||
public SvgTextView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SvgTextView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(attrs);
|
||||
}
|
||||
|
||||
private void init(AttributeSet attrs) {
|
||||
LayoutInflater.from(getContext()).inflate(R.layout.layout_svg_text, this, true);
|
||||
textView = findViewById(R.id.text);
|
||||
icon = findViewById(R.id.image);
|
||||
|
||||
// init values from custom attributes
|
||||
final TypedArray attributes =
|
||||
getContext().obtainStyledAttributes(attrs, R.styleable.SvgTextView);
|
||||
Drawable drawable = attributes.getDrawable(R.styleable.SvgTextView_svg_text_view_icon);
|
||||
if (drawable != null) {
|
||||
icon.setImageDrawable(drawable);
|
||||
}
|
||||
String str = attributes.getString(R.styleable.SvgTextView_text);
|
||||
if (!TextUtils.isEmpty(str)) {
|
||||
textView.setText(str);
|
||||
}
|
||||
|
||||
attributes.recycle();
|
||||
}
|
||||
|
||||
public void setIconClickListener(View.OnClickListener listener){
|
||||
icon.setOnClickListener(listener);
|
||||
}
|
||||
|
||||
|
||||
@BindingAdapter(value = {"svg_text_view_icon"})
|
||||
public static void bindAttr(SvgTextView svgTextView, @DrawableRes int drawable) {
|
||||
svgTextView.icon.setImageResource(drawable);
|
||||
}
|
||||
|
||||
|
||||
public void setIcon(@DrawableRes int drawable) {
|
||||
icon.setImageResource(drawable);
|
||||
}
|
||||
|
||||
public void setText(CharSequence text) {
|
||||
textView.setText(text);
|
||||
}
|
||||
}
|
||||
6
app/src/main/res/drawable/ic_choose_file.xml
Normal file
6
app/src/main/res/drawable/ic_choose_file.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<vector android:height="24dp" android:viewportHeight="1024"
|
||||
android:viewportWidth="1024" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#2b2b2b" android:pathData="M895.65,672.81c14.3,0 23.74,-9.54 23.74,-23.74L919.39,269.29a30.46,30.46 0,0 0,-8.66 -21.29L738.23,71.19A30.46,30.46 0,0 0,716.42 62L199.21,62c-52.29,0 -95.07,42.78 -95.07,95.07v654h-0.1v51.85h0.1c0,52.25 42.81,95.07 95.07,95.07h625.11c52.25,0 95.07,-42.81 95.07,-95.07v-71.31c0,-14.31 -9.54,-23.74 -23.74,-23.74s-23.74,9.54 -23.74,23.74v71.32a47.69,47.69 0,0 1,-47.48 47.58L199.21,910.51a47.72,47.72 0,0 1,-47.58 -47.58v-28.11h0.1L151.73,157.06a47.63,47.63 0,0 1,47.58 -47.48h482.47v123.57a71.32,71.32 0,0 0,71.32 71.32h118.8v344.6c-0.09,14.2 9.44,23.74 23.75,23.74zM847.19,256.81L753,256.81v0.1c-14.3,0 -23.74,-11.92 -23.74,-23.74v-98.75a2.4,2.4 0,0 1,4.13 -1.67l115.52,120a2.4,2.4 0,0 1,-1.73 4.04z"/>
|
||||
<path android:fillColor="#2b2b2b" android:pathData="M318.91,394.59c-14.78,0 -26.81,-12.25 -26.81,-27.3s12,-27.3 26.81,-27.3h300.47c14.78,0 26.81,12.25 26.81,27.3s-12,27.3 -26.81,27.3zM318.91,569.8c-14.78,0 -26.81,-12.25 -26.81,-27.3s12,-27.3 26.81,-27.3h384.85c14.78,0 26.81,12.25 26.81,27.3s-12,27.3 -26.81,27.3zM318.91,742c-14.78,0 -26.81,-12.25 -26.81,-27.3s12,-27.3 26.81,-27.3h261.3c14.78,0 26.81,12.25 26.81,27.3S595,742 580.21,742z"/>
|
||||
<path android:fillColor="#2b2b2b" android:pathData="M704.01,367.3m-27.3,0a27.3,27.3 0,1 0,54.6 0,27.3 27.3,0 1,0 -54.6,0Z"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/ic_modify.xml
Normal file
9
app/src/main/res/drawable/ic_modify.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="1024"
|
||||
android:viewportWidth="1024"
|
||||
android:width="24dp">
|
||||
<path
|
||||
android:fillColor="#2b2b2b"
|
||||
android:pathData="M768.49,388.36L590.76,215.07 210.93,594.49l-66.2,242.16v0.4L386.48,769.8zM739.52,66.62l-95.2,95.04 178.3,172.65 92.38,-92.3c48.49,-48.41 48.49,-126.99 0,-175.39 -48.4,-48.41 -127.07,-48.41 -175.47,-0zM79.03,878.71h872.33v114.98H79.03z"/>
|
||||
</vector>
|
||||
@@ -15,6 +15,22 @@
|
||||
name="progress"
|
||||
type="int"
|
||||
/>
|
||||
<variable
|
||||
name="url"
|
||||
type="String"
|
||||
/>
|
||||
<variable
|
||||
name="filePath"
|
||||
type="String"
|
||||
/>
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="com.arialyy.simple.core.upload.FtpUploadActivity"
|
||||
/>
|
||||
<variable
|
||||
name="stateStr"
|
||||
type="String"
|
||||
/>
|
||||
</data>
|
||||
|
||||
<LinearLayout
|
||||
@@ -25,11 +41,34 @@
|
||||
|
||||
<include layout="@layout/layout_bar"/>
|
||||
|
||||
<com.arialyy.simple.widget.SvgTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
bind:iconClickListener="@{() -> viewModel.chooseUrl()}"
|
||||
bind:svg_text_view_icon="@drawable/ic_modify"
|
||||
bind:text="@{@string/url(url)}"
|
||||
/>
|
||||
|
||||
<com.arialyy.simple.widget.SvgTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
bind:iconClickListener="@{() -> viewModel.chooseFilePath()}"
|
||||
bind:svg_text_view_icon="@drawable/ic_choose_file"
|
||||
bind:text="@{@string/file_path(filePath)}"
|
||||
/>
|
||||
|
||||
<include
|
||||
layout="@layout/content_single"
|
||||
layout="@layout/layout_content_single"
|
||||
bind:fileSize="@{fileSize}"
|
||||
bind:progress="@{progress}"
|
||||
bind:speed="@{speed}"
|
||||
bind:stateStr="@{stateStr}"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
77
app/src/main/res/layout/dialog_modify_url.xml
Normal file
77
app/src/main/res/layout/dialog_modify_url.xml
Normal file
@@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<data>
|
||||
<variable
|
||||
name="title"
|
||||
type="java.lang.String"
|
||||
/>
|
||||
<variable
|
||||
name="text"
|
||||
type="java.lang.String"
|
||||
/>
|
||||
</data>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/background_color"
|
||||
android:gravity="center|left"
|
||||
android:maxHeight="400dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:text="@{title}"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="22sp"
|
||||
/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/edit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@android:color/transparent"
|
||||
android:lineSpacingMultiplier="1.2"
|
||||
android:text="@{text}"
|
||||
android:textColor="#000"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
<Button
|
||||
android:id="@+id/cancel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/cancel"
|
||||
style="?buttonBarButtonStyle"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/enter"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/enter"
|
||||
style="?buttonBarButtonStyle"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
</layout>
|
||||
107
app/src/main/res/layout/layout_content_single.xml
Normal file
107
app/src/main/res/layout/layout_content_single.xml
Normal file
@@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout 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"
|
||||
>
|
||||
|
||||
<data>
|
||||
<variable
|
||||
name="fileSize"
|
||||
type="String"
|
||||
/>
|
||||
<variable
|
||||
name="speed"
|
||||
type="String"
|
||||
/>
|
||||
<variable
|
||||
name="progress"
|
||||
type="int"
|
||||
/>
|
||||
<variable
|
||||
name="stateStr"
|
||||
type="String"
|
||||
/>
|
||||
</data>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
tools:context=".core.download.SingleTaskActivity"
|
||||
tools:showIn="@layout/activity_single"
|
||||
>
|
||||
|
||||
<com.arialyy.simple.widget.HorizontalProgressBarWithNumber
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="20dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_toLeftOf="@+id/size"
|
||||
android:max="100"
|
||||
android:progress="@{progress}"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/size"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignTop="@+id/progressBar"
|
||||
android:layout_marginRight="16dp"
|
||||
android:text="@{fileSize}"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/handle_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/progressBar"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
<TextView
|
||||
android:id="@+id/speed"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@{speed}"
|
||||
android:textColor="@color/black"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/start"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:onClick="onClick"
|
||||
android:text="@{stateStr ?? @string/start}"
|
||||
style="?buttonBarButtonStyle"
|
||||
/>
|
||||
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancel"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:onClick="onClick"
|
||||
android:text="@string/delete"
|
||||
style="?buttonBarButtonStyle"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/speed_hint"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/handle_bar"
|
||||
/>
|
||||
|
||||
</RelativeLayout>
|
||||
</layout>
|
||||
29
app/src/main/res/layout/layout_svg_text.xml
Normal file
29
app/src/main/res/layout/layout_svg_text.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toLeftOf="@+id/image"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textSize="@dimen/text_size_normal"
|
||||
/>
|
||||
|
||||
<android.support.v7.widget.AppCompatImageView
|
||||
android:id="@+id/image"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:clickable="true"
|
||||
/>
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -1,16 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="HorizontalProgressBarWithNumber">
|
||||
<attr name="progress_unreached_color" format="color"/>
|
||||
<attr name="progress_reached_color" format="color"/>
|
||||
<attr name="progress_reached_bar_height" format="dimension"/>
|
||||
<attr name="progress_unreached_bar_height" format="dimension"/>
|
||||
<attr name="progress_text_size" format="dimension"/>
|
||||
<attr name="progress_text_color" format="color"/>
|
||||
<attr name="progress_text_offset" format="dimension"/>
|
||||
<attr name="progress_text_visibility" format="enum">
|
||||
<attr format="color" name="progress_unreached_color"/>
|
||||
<attr format="color" name="progress_reached_color"/>
|
||||
<attr format="dimension" name="progress_reached_bar_height"/>
|
||||
<attr format="dimension" name="progress_unreached_bar_height"/>
|
||||
<attr format="dimension" name="progress_text_size"/>
|
||||
<attr format="color" name="progress_text_color"/>
|
||||
<attr format="dimension" name="progress_text_offset"/>
|
||||
<attr format="enum" name="progress_text_visibility">
|
||||
<enum name="visible" value="0"/>
|
||||
<enum name="invisible" value="1"/>
|
||||
</attr>
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="SvgTextView">
|
||||
<attr format="reference" name="svg_text_view_icon"/>
|
||||
<attr name="text"/>
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
@@ -2,6 +2,17 @@
|
||||
<string name="app_name">Aria</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
|
||||
<string name="url">URL: %1$s</string>
|
||||
<string name="file_name">文件名: %1$s</string>
|
||||
<string name="file_path">文件路径: %1$s</string>
|
||||
<string name="enter">确认</string>
|
||||
<string name="cancel">取消</string>
|
||||
<string name="modify_url_dialog_title">修改URL</string>
|
||||
<string name="stop">停止</string>
|
||||
<string name="start">开始</string>
|
||||
<string name="resume">恢复</string>
|
||||
<string name="delete">删除</string>
|
||||
|
||||
<string-array name="main_items">
|
||||
<item>http 下载</item>
|
||||
<item>http 上传</item>
|
||||
@@ -29,9 +40,6 @@
|
||||
<item>组件中使用</item>
|
||||
</string-array>
|
||||
|
||||
<string name="file_name">文件名: %1$s</string>
|
||||
<string name="file_path">保存路径: %1$s</string>
|
||||
|
||||
|
||||
<string-array name="test_apk_download_url">
|
||||
<item>http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk</item> <!--300M的文件-->
|
||||
|
||||
25
app/src/main/res/xml/aria_fileprovider_paths.xml
Normal file
25
app/src/main/res/xml/aria_fileprovider_paths.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<root-path
|
||||
name="root"
|
||||
path="" />
|
||||
<files-path
|
||||
name="files"
|
||||
path="." />
|
||||
|
||||
<cache-path
|
||||
name="cache"
|
||||
path="." />
|
||||
|
||||
<external-path
|
||||
name="external"
|
||||
path="." />
|
||||
|
||||
<external-files-path
|
||||
name="external_file_path"
|
||||
path="." />
|
||||
<external-cache-path
|
||||
name="external_cache_path"
|
||||
path="." />
|
||||
|
||||
</paths>
|
||||
Reference in New Issue
Block a user