diff --git a/Aria/src/main/java/com/arialyy/aria/core/ConfigHelper.java b/Aria/src/main/java/com/arialyy/aria/core/ConfigHelper.java index d0df8509..6243d5ca 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/ConfigHelper.java +++ b/Aria/src/main/java/com/arialyy/aria/core/ConfigHelper.java @@ -228,7 +228,7 @@ class ConfigHelper extends DefaultHandler { } if (num < 1) { Log.e(TAG, "下载线程数不能小于 1"); - num = 3; + num = 1; } if (isDownloadConfig) { mDownloadConfig.threadNum = num; diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/BaseListener.java b/Aria/src/main/java/com/arialyy/aria/core/download/BaseListener.java index dbbed555..211a705b 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/BaseListener.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/BaseListener.java @@ -16,6 +16,7 @@ package com.arialyy.aria.core.download; import android.os.Handler; +import android.util.Log; import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.inf.AbsEntity; import com.arialyy.aria.core.inf.AbsTask; diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java index f38d1895..270b1059 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java @@ -58,22 +58,19 @@ public class DownloadReceiver extends AbsReceiver { } /** - * 加载Http下载功能 + * 加载Http、https */ - public DownloadTarget load(@NonNull String downloadUrl) { - CheckUtil.checkDownloadUrl(downloadUrl); - return new DownloadTarget(downloadUrl, targetName); + public DownloadTarget load(@NonNull String url) { + CheckUtil.checkDownloadUrl(url); + return new DownloadTarget(url, targetName); } /** - * 加载Ftp下载功能 - * - * @param serverIp ftp服务器地址 - * @param port ftp端口 - * @param filePath 需要从ftp服务器上下载的文件的路径 + * 加载ftp下载地址 */ - public FtpDownloadTarget load(String serverIp, String port, String filePath) { - return new FtpDownloadTarget(serverIp, port, filePath, targetName); + public FtpDownloadTarget loadFtp(@NonNull String url) { + CheckUtil.checkDownloadUrl(url); + return new FtpDownloadTarget(url, targetName); } /** diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java index 206e24b4..54406468 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java @@ -30,12 +30,13 @@ import java.io.File; */ public class DownloadTarget extends AbsDownloadTarget { - + protected String url; DownloadTarget(DownloadEntity entity, String targetName) { this(entity.getDownloadUrl(), targetName); } DownloadTarget(String url, String targetName) { + this.url = url; mTargetName = targetName; DownloadEntity entity = getEntity(url); mTaskEntity = DbEntity.findFirst(DownloadTaskEntity.class, "key=? and isGroupTask='false'", diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java index ba7001fc..bcf5ba5c 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java @@ -30,6 +30,11 @@ public class DownloadTaskEntity extends AbsTaskEntity { */ @Ignore public String userName, userPw, account; + /** + * FTP服务器文件或文件夹路径 + */ + public String remotePath; + /** * 下载类型 * {@link AbsTaskEntity#HTTP}、{@link AbsTaskEntity#FTP} diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java index 1f170891..af4d6097 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java @@ -21,7 +21,6 @@ import android.util.Log; import com.arialyy.aria.core.inf.AbsTaskEntity; import com.arialyy.aria.util.CommonUtil; import java.io.File; -import java.nio.charset.Charset; /** * Created by lyy on 2016/12/5. @@ -29,23 +28,22 @@ import java.nio.charset.Charset; */ public class FtpDownloadTarget extends DownloadTarget { private final String TAG = "FtpDownloadTarget"; + private String serverIp, remotePath; + private int port; - /** - * @param serverIp ftp服务器地址 - * @param port ftp端口号 - */ - FtpDownloadTarget(String serverIp, String port, String filePath, String targetName) { - this("ftp://" + serverIp + ":" + port + "/" + filePath, targetName); - } - - /** - * @param url url 为 serverIp:port/filePath - */ - private FtpDownloadTarget(String url, String targetName) { + FtpDownloadTarget(String url, String targetName) { super(url, targetName); + String[] pp = url.split("/")[2].split(":"); + this.serverIp = pp[0]; + this.port = Integer.parseInt(pp[1]); + mTaskEntity.downloadType = AbsTaskEntity.FTP; + remotePath = url.substring(url.indexOf(pp[1]) + pp[1].length(), url.length()); + if (TextUtils.isEmpty(remotePath)) { + throw new NullPointerException("ftp服务器地址不能为null"); + } int lastIndex = url.lastIndexOf("/"); mTaskEntity.downloadType = AbsTaskEntity.FTP; - mTargetName = targetName; + mTaskEntity.remotePath = remotePath; mEntity.setFileName(url.substring(lastIndex + 1, url.length())); } @@ -117,6 +115,14 @@ public class FtpDownloadTarget extends DownloadTarget { mTaskEntity.userName = userName; mTaskEntity.userPw = password; mTaskEntity.account = account; + //FtpClientHelp.getInstnce().login(serverIp, port, userName, password, account); return this; } + + ///** + // * 当所有任务都完成时,需要登出ftp服务器 + // */ + //public void logout() { + // FtpClientHelp.getInstnce().logout(); + //} } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/Downloader.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/Downloader.java index f3821aa1..ed504a61 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/Downloader.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/Downloader.java @@ -16,6 +16,7 @@ package com.arialyy.aria.core.download.downloader; import android.content.Context; +import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; import com.arialyy.aria.core.AriaManager; @@ -33,6 +34,8 @@ import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import org.apache.commons.net.ftp.FTPClient; +import org.apache.commons.net.ftp.FTPReply; /** * Created by AriaL on 2017/7/1. @@ -416,6 +419,7 @@ class Downloader implements Runnable, IDownloadUtil { private AbsThreadTask createThreadTask(SubThreadConfig config) { switch (mTaskEntity.downloadType) { case AbsTaskEntity.FTP: + config.remotePath = mTaskEntity.remotePath; return new FtpThreadTask(mConstance, mListener, config); case AbsTaskEntity.HTTP: return new HttpThreadTask(mConstance, mListener, config); diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpClientHelp.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpClientHelp.java new file mode 100644 index 00000000..a9172836 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpClientHelp.java @@ -0,0 +1,117 @@ +/* + * 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.aria.core.download.downloader; + +import android.text.TextUtils; +import android.util.Log; +import com.arialyy.aria.core.AriaManager; +import java.io.IOException; +import org.apache.commons.net.ftp.FTPClient; +import org.apache.commons.net.ftp.FTPReply; + +/** + * Created by Aria.Lao on 2017/7/26. + */ +public class FtpClientHelp { + private final String TAG = "FtpClientHelp"; + private static volatile FtpClientHelp INSTANCE = null; + + private FTPClient client; + private String serverIp, user, pw, account; + private int port; + + private FtpClientHelp() { + } + + public static FtpClientHelp getInstnce() { + if (INSTANCE == null) { + synchronized (AriaManager.LOCK) { + INSTANCE = new FtpClientHelp(); + } + } + return INSTANCE; + } + + public FTPClient getClient() { + if (client == null || !client.isConnected()) { + createClient(); + } + return client; + } + + /** + * 登录到FTP服务器,当客户端为null或客户端没有连接到FTP服务器时才会执行登录操作 + */ + public void login(String serverIp, int port, String user, String pw, String account) { + this.serverIp = serverIp; + this.port = port; + this.user = user; + this.pw = pw; + this.account = account; + if (client == null || !client.isConnected()) { + createClient(); + } + } + + /** + * 登出 + */ + public void logout() { + try { + if (client != null && client.isConnected()) { + client.logout(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + FTPClient createClient() { + new Thread(new Runnable() { + @Override public void run() { + client = new FTPClient(); + try { + client.connect(serverIp, port); + if (!TextUtils.isEmpty(account)) { + client.login(user, pw); + } else { + client.login(user, pw, account); + } + int reply = client.getReplyCode(); + if (!FTPReply.isPositiveCompletion(reply)) { + client.disconnect(); + Log.e(TAG, "无法连接到ftp服务器,错误码为:" + reply); + } + } catch (IOException e) { + Log.d(TAG, e.getMessage()); + } finally { + synchronized (FtpClientHelp.this) { + FtpClientHelp.this.notify(); + } + } + } + }).start(); + synchronized (FtpClientHelp.this) { + try { + wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + return client; + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpFileInfoThread.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpFileInfoThread.java index e606fb81..29401a01 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpFileInfoThread.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpFileInfoThread.java @@ -51,11 +51,8 @@ class FtpFileInfoThread implements Runnable { FTPClient client = null; try { client = new FTPClient(); - //ip和端口 - String[] temp = mEntity.getDownloadUrl().split("/"); - String[] pp = temp[2].split(":"); - //String dir = temp[temp.length - 2]; - String fileName = temp[temp.length - 1]; + String[] pp = mEntity.getDownloadUrl().split("/")[2].split(":"); + String fileName = mTaskEntity.remotePath; client.connect(pp[0], Integer.parseInt(pp[1])); if (!TextUtils.isEmpty(mTaskEntity.account)) { client.login(mTaskEntity.userName, mTaskEntity.userPw); diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpThreadTask.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpThreadTask.java index c4d8ff3f..f5fe280a 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpThreadTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpThreadTask.java @@ -15,20 +15,14 @@ */ package com.arialyy.aria.core.download.downloader; -import android.os.Handler; -import android.os.Message; import android.text.TextUtils; import android.util.Log; import com.arialyy.aria.util.BufferedRandomAccessFile; -import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.util.Timer; -import java.util.TimerTask; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; -import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPReply; /** @@ -57,12 +51,9 @@ class FtpThreadTask extends AbsThreadTask { + ",结束位置:" + mConfig.END_LOCATION + "】"); - client = new FTPClient(); - //ip和端口 String[] temp = mEntity.getDownloadUrl().split("/"); String[] pp = temp[2].split(":"); - //String dir = temp[temp.length - 2]; - String fileName = temp[temp.length - 1]; + client = new FTPClient(); client.connect(pp[0], Integer.parseInt(pp[1])); if (!TextUtils.isEmpty(mTaskEntity.account)) { client.login(mTaskEntity.userName, mTaskEntity.userPw); @@ -79,14 +70,14 @@ class FtpThreadTask extends AbsThreadTask { client.enterLocalPassiveMode(); client.setFileType(FTP.BINARY_FILE_TYPE); client.setRestartOffset(mConfig.START_LOCATION); - is = client.retrieveFileStream(fileName); + client.allocate(mBufSize); + is = client.retrieveFileStream(mConfig.remotePath); file = new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", mBufSize); file.seek(mConfig.START_LOCATION); byte[] buffer = new byte[mBufSize]; int len; //当前子线程的下载位置 mChildCurrentLocation = mConfig.START_LOCATION; - //TODO: 2017/7/25 隐藏问题,速度太快(20m/s)或文件太小,秒下,会出现 ftp Connection reset by peer 问题 while ((len = is.read(buffer)) != -1) { if (STATE.isCancel) break; if (STATE.isStop) break; @@ -102,7 +93,6 @@ class FtpThreadTask extends AbsThreadTask { } } if (STATE.isCancel || STATE.isStop) return; - //if (client.completePendingCommand()) { Log.i(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】线程__" + mConfig.THREAD_ID + "__下载完毕"); writeConfig(true, 1); STATE.COMPLETE_THREAD_NUM++; @@ -120,14 +110,13 @@ class FtpThreadTask extends AbsThreadTask { failDownload(mChildCurrentLocation, "获取流失败", e); } finally { try { - if (file != null){ + if (file != null) { file.close(); } - if (is != null){ + if (is != null) { is.close(); } if (client != null && client.isConnected()) { - //client.logout(); client.disconnect(); } } catch (IOException e) { diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/SubThreadConfig.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/SubThreadConfig.java index aba3f53f..077b1d50 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/SubThreadConfig.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/SubThreadConfig.java @@ -2,6 +2,7 @@ package com.arialyy.aria.core.download.downloader; import com.arialyy.aria.core.download.DownloadTaskEntity; import java.io.File; +import org.apache.commons.net.ftp.FTPClient; /** * 子线程下载信息类 @@ -21,4 +22,7 @@ class SubThreadConfig { String CONFIG_FILE_PATH; DownloadTaskEntity DOWNLOAD_TASK_ENTITY; boolean IS_SUPPORT_BREAK_POINT = true; + FTPClient client; + //远程地址 + String remotePath; } \ No newline at end of file diff --git a/app/src/main/assets/aria_config.xml b/app/src/main/assets/aria_config.xml index 7e615062..bbda9fa1 100644 --- a/app/src/main/assets/aria_config.xml +++ b/app/src/main/assets/aria_config.xml @@ -8,7 +8,7 @@ - + diff --git a/app/src/main/java/com/arialyy/simple/download/FtpDownloadActivity.java b/app/src/main/java/com/arialyy/simple/download/FtpDownloadActivity.java index 17330201..90a1d46a 100644 --- a/app/src/main/java/com/arialyy/simple/download/FtpDownloadActivity.java +++ b/app/src/main/java/com/arialyy/simple/download/FtpDownloadActivity.java @@ -20,6 +20,7 @@ import android.util.Log; import android.view.View; import com.arialyy.annotations.Download; import com.arialyy.aria.core.Aria; +import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.aria.util.CommonUtil; import com.arialyy.frame.util.show.L; @@ -34,28 +35,40 @@ import java.io.File; * Ftp下载测试 */ public class FtpDownloadActivity extends BaseActivity { + //private final String URL = "ftp://172.18.104.129:21/haha/large.rar"; + private final String URL = "ftp://172.18.104.129:21/cd.mp3"; @Override protected void init(Bundle savedInstanceState) { super.init(savedInstanceState); + setTitle("FTP文件下载"); Aria.download(this).register(); + DownloadEntity entity = Aria.download(this).getDownloadEntity(URL); + if (entity != null) { + getBinding().setFileSize(entity.getConvertFileSize()); + if (entity.getFileSize() == 0) { + getBinding().setProgress(0); + } else { + getBinding().setProgress(entity.isComplete() ? 100 + : (int) (entity.getCurrentProgress() * 100 / entity.getFileSize())); + } + } } public void onClick(View view) { switch (view.getId()) { case R.id.start: Aria.download(this) - //.load("172.18.104.129", "21", "cd.mp3") - //.load("192.168.1.8", "21", "gg.png") - .load("192.168.1.8", "21", "23.pdf") - //.load("192.168.1.8", "21", "heh.txt") + .loadFtp(URL) .login("lao", "123456") - .setDownloadPath("/mnt/sdcard/tt.png") + .setDownloadPath("/mnt/sdcard/") .charSet("gbk") .start(); break; case R.id.stop: + Aria.download(this).loadFtp(URL).stop(); break; case R.id.cancel: + Aria.download(this).loadFtp(URL).cancel(); break; } } @@ -97,6 +110,7 @@ public class FtpDownloadActivity extends BaseActivity " + CommonUtil.getFileMD5(new File(task.getDownloadPath()))); T.showShort(this, "FTP下载完成"); diff --git a/app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java b/app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java index b6b8528d..383d8ddc 100644 --- a/app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java +++ b/app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java @@ -23,7 +23,6 @@ import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.RadioGroup; -import android.widget.TextView; import android.widget.Toast; import butterknife.Bind; import com.arialyy.annotations.Download; @@ -41,8 +40,7 @@ public class SingleTaskActivity extends BaseActivity { private static final String DOWNLOAD_URL = //"http://kotlinlang.org/docs/kotlin-docs.pdf"; //"https://atom-installer.github.com/v1.13.0/AtomSetup.exe?s=1484074138&ext=.exe"; - //"http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk"; - "https://d.pcs.baidu.com/file/7330524ec2affe80914cd306e16fd0ac?fid=3965548007-250528-918323254381453&time=1500859695&rt=sh&sign=FDTAERVY-DCb740ccc5511e5e8fedcff06b081203-7u09%2BsA23HuD53M3bCJpH1HVp3o%3D&expires=8h&chkv=1&chkbd=0&chkpc=et&dp-logid=4740488282618906999&dp-callid=0&r=714336419"; + "http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk"; //"http://down2.xiaoshuofuwuqi.com/d/file/filetxt/20170608/14/%BA%DA%CE%D7%CA%A6%E1%C8%C6%F0.txt"; //"http://tinghuaapp.oss-cn-shanghai.aliyuncs.com/20170612201739607815"; //"http://static.gaoshouyou.com/d/36/69/2d3699acfa69e9632262442c46516ad8.apk"; diff --git a/app/src/main/java/com/arialyy/simple/download/fragment_download/DownloadFragment.java b/app/src/main/java/com/arialyy/simple/download/fragment_download/DownloadFragment.java index 8e34589b..5fd45147 100644 --- a/app/src/main/java/com/arialyy/simple/download/fragment_download/DownloadFragment.java +++ b/app/src/main/java/com/arialyy/simple/download/fragment_download/DownloadFragment.java @@ -42,7 +42,7 @@ public class DownloadFragment extends AbsFragment { @Bind(R.id.stop) Button mStop; @Bind(R.id.cancel) Button mCancel; - private static final String DOWNLOAD_URL = "http://static.ilongyuan.cn/rayark/RayarkFZ_2.0.7.apk"; + private static final String DOWNLOAD_URL = "https://res5.d.cn/2137e42d610b3488d9420c6421529386eee5bdbfd9be1fafe0a05d6dabaec8c156ddbd00581055bbaeac03904fb63310e80010680235d16bd4c040b50096a0c20dd1c4b0854529a1.apk"; @Override protected void init(Bundle savedInstanceState) { if (Aria.download(this).taskExists(DOWNLOAD_URL)) { @@ -65,7 +65,7 @@ public class DownloadFragment extends AbsFragment { case R.id.start: Aria.download(this) .load(DOWNLOAD_URL) - .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/兰空VOEZ.apk") + .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/王者军团.apk") .start(); break; case R.id.stop: @@ -84,13 +84,13 @@ public class DownloadFragment extends AbsFragment { @Download.onTaskStop public void onTaskStop(DownloadTask task) { setBtState(true); - getBinding().setSpeed("0.0kb/s"); + getBinding().setSpeed(""); } @Download.onTaskCancel public void onTaskCancel(DownloadTask task) { setBtState(true); getBinding().setProgress(0); - getBinding().setSpeed("0.0kb/s"); + getBinding().setSpeed(""); } @Download.onTaskRunning public void onTaskRunning(DownloadTask task) { diff --git a/app/src/main/java/com/arialyy/simple/download/group/DownloadGroupActivity.java b/app/src/main/java/com/arialyy/simple/download/group/DownloadGroupActivity.java index cfa5edba..431b5b8a 100644 --- a/app/src/main/java/com/arialyy/simple/download/group/DownloadGroupActivity.java +++ b/app/src/main/java/com/arialyy/simple/download/group/DownloadGroupActivity.java @@ -89,6 +89,9 @@ public class DownloadGroupActivity extends BaseActivity + + - https://res5.d.cn/5a6a3384c1b2be1a65d84b914e6a6fef697637578b6db2eb1056d50b09cf1dcf289d4045df7ef95746e498e3d6a848ab84c89b77aa60194e2c48e5a7cb748265.apk - https://res5.d.cn/5a6a3384c1b2be1a52034c72752e8475414630ebc69318b84ef584115ebf5eaaab945ae07b7fe3596afc72a7940ff328d4a9553f6ae92d6c09ba4bfb533137f6.apk - https://res5.d.cn/5a6a3384c1b2be1a426f06bfc69034d69c44ae1a01da180cab8e59bd1a5e1a784bac46ba0c64579d14f0e80a4ce4f068af89b0369a393456f4f449a8829cad5c.apk + + + - - + http://static.gaoshouyou.com/d/12/0d/7f120f50c80d2e7b8c4ba24ece4f9cdd.apk + http://static.ilongyuan.cn/rayark/RayarkFZ_2.0.7.apk 王者荣耀.apk 战斗吧剑灵.apk - 天魔幻想.apk +