├── 1706328825823.jpg ├── HybridFileXfer-Android ├── .gitignore ├── .idea │ ├── .gitignore │ ├── .name │ ├── compiler.xml │ ├── deploymentTargetSelector.xml │ ├── gradle.xml │ ├── misc.xml │ ├── runConfigurations.xml │ └── vcs.xml ├── app │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── top │ │ │ └── weixiansen574 │ │ │ └── hybridfilexfer2 │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── aidl │ │ │ └── top │ │ │ │ └── weixiansen574 │ │ │ │ └── hybridfilexfer │ │ │ │ └── aidl │ │ │ │ ├── IIOService.aidl │ │ │ │ └── ParcelableRemoteFile.aidl │ │ ├── cpp │ │ │ ├── CMakeLists.txt │ │ │ └── native-memory.cpp │ │ ├── java │ │ │ └── top │ │ │ │ └── weixiansen574 │ │ │ │ ├── async │ │ │ │ ├── BackstageTask.java │ │ │ │ └── TaskManger.java │ │ │ │ ├── hybridfilexfer │ │ │ │ ├── ClientActivity.java │ │ │ │ ├── Config.java │ │ │ │ ├── ConfigDB.java │ │ │ │ ├── IOService.java │ │ │ │ ├── IOServiceImpl.java │ │ │ │ ├── MainActivity.java │ │ │ │ ├── NativeMemory.java │ │ │ │ ├── NetCardIcon.java │ │ │ │ ├── TransferActivity.java │ │ │ │ ├── TransferDialog.java │ │ │ │ ├── aidl │ │ │ │ │ └── ParcelableRemoteFile.java │ │ │ │ ├── bean │ │ │ │ │ └── BookMark.java │ │ │ │ ├── core │ │ │ │ │ ├── ControllerIdentifiers.java │ │ │ │ │ ├── FileBlock.java │ │ │ │ │ ├── HFXClient.java │ │ │ │ │ ├── HFXService.java │ │ │ │ │ ├── ReadFileCall.java │ │ │ │ │ ├── ReceiveFileCall.java │ │ │ │ │ ├── SendFileCall.java │ │ │ │ │ ├── SpeedMonitorThread.java │ │ │ │ │ ├── TransferConnection.java │ │ │ │ │ ├── TransferIdentifiers.java │ │ │ │ │ ├── Utils.java │ │ │ │ │ ├── WriteFileCall.java │ │ │ │ │ ├── bean │ │ │ │ │ │ ├── Directory.java │ │ │ │ │ │ ├── RemoteFile.java │ │ │ │ │ │ ├── ServerNetInterface.java │ │ │ │ │ │ └── TrafficInfo.java │ │ │ │ │ └── callback │ │ │ │ │ │ ├── ClientCallBack.java │ │ │ │ │ │ ├── ConnectServerCallback.java │ │ │ │ │ │ └── TransferFileCallback.java │ │ │ │ ├── droidcore │ │ │ │ │ ├── DisconnectTask.java │ │ │ │ │ ├── DroidHFXClient.java │ │ │ │ │ ├── DroidReadFileCall.java │ │ │ │ │ ├── DroidWriteFileCall.java │ │ │ │ │ ├── HFXServer.java │ │ │ │ │ ├── StartServerTask.java │ │ │ │ │ └── callback │ │ │ │ │ │ └── StartServerCallback.java │ │ │ │ ├── listadapter │ │ │ │ │ ├── BookmarkAdapter.java │ │ │ │ │ ├── FileSelectAdapter.java │ │ │ │ │ ├── LocalFileSelectAdapter.java │ │ │ │ │ ├── NetCardsAdapter.java │ │ │ │ │ └── RemoteFileSelectAdapter.java │ │ │ │ └── tasks │ │ │ │ │ ├── BTransferFileCallback.java │ │ │ │ │ ├── ClientTask.java │ │ │ │ │ ├── ConnectServerTask.java │ │ │ │ │ ├── DeleteFilesTask.java │ │ │ │ │ ├── ListFilesTask.java │ │ │ │ │ ├── SendFilesToRemoteTask.java │ │ │ │ │ └── SendFilesToShelfTask.java │ │ │ │ └── nio │ │ │ │ └── DataByteChannel.java │ │ └── res │ │ │ ├── anim │ │ │ └── list_anim.xml │ │ │ ├── drawable │ │ │ ├── baseline_add_24.xml │ │ │ ├── baseline_arrow_outward_24.xml │ │ │ ├── baseline_bookmark_add_24.xml │ │ │ ├── baseline_bookmarks_24.xml │ │ │ ├── baseline_check_circle_24.xml │ │ │ ├── baseline_delete_24.xml │ │ │ ├── baseline_file_download_24.xml │ │ │ ├── baseline_grid_view_24.xml │ │ │ ├── baseline_more_vert_24.xml │ │ │ ├── baseline_phonelink_ring_24.xml │ │ │ ├── baseline_refresh_24.xml │ │ │ ├── baseline_select_all_24.xml │ │ │ ├── baseline_speed_24.xml │ │ │ ├── baseline_update_24.xml │ │ │ ├── baseline_upload_24.xml │ │ │ ├── bt.xml │ │ │ ├── ethernet.xml │ │ │ ├── file.xml │ │ │ ├── folder.xml │ │ │ ├── github.xml │ │ │ ├── ic_close.xml │ │ │ ├── logo.png │ │ │ ├── shadow_bottom.xml │ │ │ ├── shadow_left.xml │ │ │ ├── shadow_right.xml │ │ │ ├── shadow_top.xml │ │ │ ├── usb.xml │ │ │ └── wifi.xml │ │ │ ├── layout │ │ │ ├── activity_client.xml │ │ │ ├── activity_main.xml │ │ │ ├── activity_transfer.xml │ │ │ ├── dialog_bookmarks.xml │ │ │ ├── dialog_buffer_settings.xml │ │ │ ├── dialog_connect_server.xml │ │ │ ├── dialog_transfer.xml │ │ │ ├── edit_text.xml │ │ │ ├── item_bookmark.xml │ │ │ ├── item_file.xml │ │ │ ├── item_net_card_info.xml │ │ │ ├── item_net_interface_status.xml │ │ │ └── toolbar_select.xml │ │ │ ├── menu │ │ │ ├── main_menu.xml │ │ │ ├── select_toolbar_menu.xml │ │ │ └── toolbar_menu.xml │ │ │ ├── values-ja-rJP │ │ │ └── strings.xml │ │ │ ├── values-ko │ │ │ └── strings.xml │ │ │ ├── values-night │ │ │ └── colors.xml │ │ │ ├── values-zh-rTW │ │ │ └── strings.xml │ │ │ ├── values-zh │ │ │ └── strings.xml │ │ │ ├── values │ │ │ ├── arrays.xml │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── themes.xml │ │ │ └── xml │ │ │ ├── backup_rules.xml │ │ │ └── data_extraction_rules.xml │ │ └── test │ │ └── java │ │ └── top │ │ └── weixiansen574 │ │ └── hybridfilexfer2 │ │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── HybridFileXfer-PC ├── .idea │ ├── .gitignore │ ├── HybridFileXfer-PC.iml │ ├── artifacts │ │ └── HybridFileXfer_PC_jar.xml │ ├── encodings.xml │ ├── misc.xml │ ├── modules.xml │ ├── uiDesigner.xml │ └── vcs.xml ├── AdbWinApi.dll ├── AdbWinUsbApi.dll ├── HybridFileXfer-PC.iml ├── adb.exe ├── out │ ├── artifacts │ │ └── HybridFileXfer_PC_jar │ │ │ └── HybridFileXfer-PC.jar │ └── production │ │ └── HybridFileXfer-PC │ │ ├── META-INF │ │ └── MANIFEST.MF │ │ ├── messages_en.properties │ │ ├── messages_ja.properties │ │ ├── messages_ko.properties │ │ ├── messages_zh_CN.properties │ │ ├── messages_zh_TW.properties │ │ └── top │ │ └── weixiansen574 │ │ ├── hybridfilexfer │ │ ├── Main$1.class │ │ ├── Main$2.class │ │ ├── Main.class │ │ ├── Strings$1.class │ │ ├── Strings.class │ │ ├── core │ │ │ ├── ControllerIdentifiers.class │ │ │ ├── FileBlock.class │ │ │ ├── HFXClient.class │ │ │ ├── HFXService.class │ │ │ ├── ReadFileCall.class │ │ │ ├── ReceiveFileCall.class │ │ │ ├── SendFileCall.class │ │ │ ├── SpeedMonitorThread.class │ │ │ ├── TransferConnection.class │ │ │ ├── TransferIdentifiers.class │ │ │ ├── Utils.class │ │ │ ├── WriteFileCall.class │ │ │ ├── bean │ │ │ │ ├── Directory.class │ │ │ │ ├── RemoteFile.class │ │ │ │ ├── ServerNetInterface.class │ │ │ │ └── TrafficInfo.class │ │ │ └── callback │ │ │ │ ├── ClientCallBack.class │ │ │ │ ├── ConnectServerCallback.class │ │ │ │ └── TransferFileCallback.class │ │ └── jdkcore │ │ │ ├── JdkHFXClient.class │ │ │ ├── JdkReadFileCall.class │ │ │ └── JdkWriteFileCall.class │ │ └── nio │ │ └── DataByteChannel.class ├── src │ ├── META-INF │ │ └── MANIFEST.MF │ ├── messages_en.properties │ ├── messages_ja.properties │ ├── messages_ko.properties │ ├── messages_zh_CN.properties │ ├── messages_zh_TW.properties │ └── top │ │ └── weixiansen574 │ │ ├── hybridfilexfer │ │ ├── Main.java │ │ ├── Strings.java │ │ ├── core │ │ │ ├── ControllerIdentifiers.java │ │ │ ├── FileBlock.java │ │ │ ├── HFXClient.java │ │ │ ├── HFXService.java │ │ │ ├── ReadFileCall.java │ │ │ ├── ReceiveFileCall.java │ │ │ ├── SendFileCall.java │ │ │ ├── SpeedMonitorThread.java │ │ │ ├── TransferConnection.java │ │ │ ├── TransferIdentifiers.java │ │ │ ├── Utils.java │ │ │ ├── WriteFileCall.java │ │ │ ├── bean │ │ │ │ ├── Directory.java │ │ │ │ ├── RemoteFile.java │ │ │ │ ├── ServerNetInterface.java │ │ │ │ └── TrafficInfo.java │ │ │ └── callback │ │ │ │ ├── ClientCallBack.java │ │ │ │ ├── ConnectServerCallback.java │ │ │ │ └── TransferFileCallback.java │ │ └── jdkcore │ │ │ ├── JdkHFXClient.java │ │ │ ├── JdkReadFileCall.java │ │ │ └── JdkWriteFileCall.java │ │ └── nio │ │ └── DataByteChannel.java ├── start.c └── start.exe ├── IMG_20241125_235527.jpg ├── LICENSE.txt ├── PixPin_2024-04-15_20-42-19.png ├── PixPin_2024-04-15_20-45-49.png ├── README.md ├── Screenshot_2024-10-13-13-20-59-747_top.weixiansen574.hybridfilexfer.jpg ├── Screenshot_2024-10-13-13-21-20-325_top.weixiansen574.hybridfilexfer.jpg ├── Screenshot_2024-10-13-13-59-51-358_top.weixiansen574.hybridfilexfer.jpg ├── Screenshot_2024-10-13-14-00-12-221_top.weixiansen574.hybridfilexfer.jpg ├── Screenshot_2024-10-13-14-16-19-518_top.weixiansen574.hybridfilexfer.jpg ├── Screenshot_2024-10-13-14-16-22-997_top.weixiansen574.hybridfilexfer.jpg ├── Screenshot_2024-10-13-14-20-12-558_top.weixiansen574.hybridfilexfer.jpg ├── script ├── USB-forward.bat ├── USB-forward.sh ├── USB-forward_中文.bat ├── launch-android-app.bat ├── start-by-adb.bat └── start-by-network.bat ├── 手机对传.jpg ├── 赞助名单.md └── 飞机杯社区(迫真).svg /1706328825823.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/1706328825823.jpg -------------------------------------------------------------------------------- /HybridFileXfer-Android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/.idea/.name: -------------------------------------------------------------------------------- 1 | HybridFileXfer -------------------------------------------------------------------------------- /HybridFileXfer-Android/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/.idea/deploymentTargetSelector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 21 | 22 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 17 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /release -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | } 4 | 5 | android { 6 | namespace 'top.weixiansen574.hybridfilexfer' 7 | compileSdk 34 8 | 9 | defaultConfig { 10 | //applicationId "com.antutu.ABenchMark" //改成此包名提升传输速度😆 11 | applicationId "top.weixiansen574.hybridfilexfer" 12 | minSdk 24 13 | targetSdk 34 14 | versionCode 300 15 | versionName "3.0.0 - beta" 16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 17 | ndk { 18 | abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64"// 指定目标 CPU 架构 19 | } 20 | } 21 | 22 | externalNativeBuild { 23 | cmake { 24 | path "src/main/cpp/CMakeLists.txt" // 指定 CMakeLists.txt 位置 25 | } 26 | } 27 | 28 | buildFeatures { 29 | viewBinding true 30 | buildConfig = true 31 | aidl = true 32 | } 33 | 34 | buildTypes { 35 | release { 36 | minifyEnabled true 37 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 38 | } 39 | } 40 | compileOptions { 41 | sourceCompatibility JavaVersion.VERSION_1_8 42 | targetCompatibility JavaVersion.VERSION_1_8 43 | } 44 | } 45 | 46 | dependencies { 47 | /*implementation 'androidx.appcompat:appcompat:1.7.0'*/ 48 | implementation 'com.google.android.material:material:1.12.0' 49 | implementation 'androidx.constraintlayout:constraintlayout:2.2.0' 50 | implementation 'androidx.appcompat:appcompat:1.7.0' 51 | testImplementation 'junit:junit:4.13.2' 52 | androidTestImplementation 'androidx.test.ext:junit:1.2.1' 53 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' 54 | implementation "dev.rikka.shizuku:api:13.1.5" 55 | implementation "dev.rikka.shizuku:provider:13.1.5" 56 | implementation "io.github.l4digital:fastscroll:2.1.0" 57 | } -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -dontobfuscate 23 | -keep class top.weixiansen574.** { *; } -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/androidTest/java/top/weixiansen574/hybridfilexfer2/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer2; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("top.weixainsen574.hybridfilexfer2", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 24 | 27 | 28 | 32 | 33 | 34 | 41 | 42 | 46 | 52 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/aidl/top/weixiansen574/hybridfilexfer/aidl/IIOService.aidl: -------------------------------------------------------------------------------- 1 | // IIOService.aidl 2 | package top.weixiansen574.hybridfilexfer.aidl; 3 | 4 | import top.weixiansen574.hybridfilexfer.aidl.ParcelableRemoteFile; 5 | 6 | interface IIOService { 7 | ParcelFileDescriptor createAndOpenWriteableFile(String path, long length) = 1; 8 | String createParentDirIfNotExists(String path) = 12; 9 | boolean setFileLastModified(String path, long time) = 5; 10 | ParcelFileDescriptor openReadableFile(String path) = 2; 11 | String tryMkdirs(String path) = 13; 12 | int[] listFiles(String path) = 3; 13 | List getAndRemoveFileListSlice(int sliceId) = 4; 14 | boolean deleteFile(String path) = 6; 15 | boolean fileExists(String path) = 7; 16 | boolean appendAndMkdirs(String parent, String child) = 8; 17 | boolean mkdirs(String path) = 9; 18 | boolean isFile(String path) = 10; 19 | String getFileParent(String path) = 11; 20 | void destroy() = 16777114; 21 | } 22 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/aidl/top/weixiansen574/hybridfilexfer/aidl/ParcelableRemoteFile.aidl: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.aidl; 2 | 3 | parcelable ParcelableRemoteFile; -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4.1) 2 | 3 | project("hybridfilexfer") 4 | 5 | add_library(native-memory SHARED native-memory.cpp) 6 | 7 | find_library(log-lib log) 8 | 9 | target_link_libraries(native-memory 10 | android 11 | log) -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/cpp/native-memory.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define LOG_TAG "JNI_MEMORY" 6 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) 7 | //我不会c++,代码由ChatGPT生成 8 | extern "C" 9 | JNIEXPORT jobject JNICALL 10 | Java_top_weixiansen574_hybridfilexfer_NativeMemory_allocateLargeBuffer(JNIEnv *env, jclass clazz, 11 | jint size) { 12 | void *buffer = malloc(size); 13 | if (!buffer) { 14 | LOGE("malloc failed! Requested size: %d", size); 15 | return nullptr; 16 | } 17 | return env->NewDirectByteBuffer(buffer, size); 18 | } 19 | 20 | extern "C" 21 | JNIEXPORT void JNICALL 22 | Java_top_weixiansen574_hybridfilexfer_NativeMemory_freeBuffer(JNIEnv *env, jclass clazz, 23 | jobject byteBuffer) { 24 | void *buffer = env->GetDirectBufferAddress(byteBuffer); 25 | if (buffer) { 26 | free(buffer); 27 | //LOGE("Buffer freed successfully"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/async/BackstageTask.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.async; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.lang.reflect.InvocationTargetException; 5 | import java.lang.reflect.Method; 6 | import java.lang.reflect.Proxy; 7 | import java.util.ArrayList; 8 | import java.util.Arrays; 9 | import java.util.LinkedList; 10 | import java.util.List; 11 | 12 | 13 | public abstract class BackstageTask implements Runnable{ 14 | private final T uiHandler; 15 | private boolean executed = false; 16 | private boolean isComplete = false; 17 | public BackstageTask(T uiHandler) { 18 | this.uiHandler = uiHandler; 19 | } 20 | 21 | protected abstract void onStart(T eventHandlerProxy) throws Throwable; 22 | 23 | protected void onError(Throwable th){} 24 | 25 | protected void onComplete(){} 26 | 27 | @SuppressWarnings("unchecked") 28 | @Override 29 | public void run() { 30 | List> interfaces = new LinkedList<>(); 31 | Class clazz = uiHandler.getClass(); 32 | while (clazz != null && clazz != Object.class) { 33 | interfaces.addAll(Arrays.asList(clazz.getInterfaces())); 34 | clazz = clazz.getSuperclass(); 35 | } 36 | T proxyInstance = (T) Proxy.newProxyInstance(uiHandler.getClass().getClassLoader(), 37 | interfaces.toArray(new Class[0]), 38 | new EvProxyHandler(uiHandler)); 39 | try { 40 | onStart(proxyInstance); 41 | onComplete(); 42 | TaskManger.postOnUiThread(uiHandler::onComplete); 43 | isComplete = true; 44 | } catch (Throwable e) { 45 | e.printStackTrace(); 46 | onError(e); 47 | TaskManger.postOnUiThread(() -> uiHandler.onError(e)); 48 | } 49 | } 50 | 51 | 52 | public synchronized void execute() { 53 | if (executed){ 54 | throw new RuntimeException("Task has been executed"); 55 | } 56 | executed = true; 57 | TaskManger.start(this); 58 | } 59 | 60 | public boolean isExecuted() { 61 | return executed; 62 | } 63 | 64 | public boolean isComplete() { 65 | return isComplete; 66 | } 67 | 68 | public static class EvProxyHandler implements InvocationHandler { 69 | Object evHandler; 70 | 71 | public EvProxyHandler(Object evHandler) { 72 | this.evHandler = evHandler; 73 | } 74 | 75 | @Override 76 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 77 | if (method.getDeclaringClass() == Object.class){ 78 | return method.invoke(proxy,args); 79 | } 80 | TaskManger.postOnUiThread(() -> { 81 | try { 82 | method.invoke(evHandler,args); 83 | } catch (IllegalAccessException | InvocationTargetException e) { 84 | throw new RuntimeException(e); 85 | } 86 | }); 87 | return null; 88 | } 89 | } 90 | 91 | public interface BaseEventHandler{ 92 | default void onError(Throwable th) { 93 | throw new RuntimeException(th); 94 | } 95 | 96 | default void onComplete() { 97 | } 98 | } 99 | 100 | } 101 | 102 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/async/TaskManger.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.async; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | 6 | public class TaskManger { 7 | private static volatile Handler mainThreadHandler; 8 | private static Handler getUiThreadHandler() { 9 | if (mainThreadHandler == null) { 10 | synchronized (TaskManger.class) { 11 | if (mainThreadHandler == null) { 12 | mainThreadHandler = new Handler(Looper.getMainLooper()); 13 | } 14 | } 15 | } 16 | return mainThreadHandler; 17 | } 18 | 19 | public static void postOnUiThread(Runnable runnable) { 20 | getUiThreadHandler().post(runnable); 21 | } 22 | public static void start(Runnable runnable){ 23 | Thread thread = new Thread(runnable); 24 | thread.setName(runnable.getClass().getSimpleName()); 25 | thread.start(); 26 | } 27 | public static void execute(BackstageTask backstageTask){ 28 | start(backstageTask); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/Config.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | 6 | public class Config { 7 | public static final int MODE_NORMAL = 0; 8 | public static final int MODE_ROOT = 1; 9 | private static Config instance; 10 | SharedPreferences preferences; 11 | 12 | public Config(SharedPreferences preferences) { 13 | this.preferences = preferences; 14 | } 15 | 16 | public static synchronized Config getInstance(Context context) { 17 | if (instance == null){ 18 | instance = new Config(context.getApplicationContext().getSharedPreferences("config",Context.MODE_PRIVATE)); 19 | } 20 | return instance; 21 | } 22 | 23 | public int getMode(){ 24 | return preferences.getInt("mode",MODE_NORMAL); 25 | } 26 | 27 | public void setMode(int mode){ 28 | preferences.edit().putInt("mode",mode).apply(); 29 | } 30 | 31 | public int getServerPort() { 32 | return 5740; 33 | } 34 | 35 | public int getLocalBufferCount() { 36 | return preferences.getInt("local_buffer_count",256); 37 | } 38 | 39 | public void setLocalBufferCount(int count){ 40 | preferences.edit().putInt("local_buffer_count",count).apply(); 41 | } 42 | 43 | public int getRemoteBufferCount() { 44 | return preferences.getInt("remote_buffer_count",512); 45 | } 46 | 47 | public void setRemoteBufferCount(int count){ 48 | preferences.edit().putInt("remote_buffer_count",count).apply(); 49 | } 50 | 51 | public void setClientIOMode(int mode){ 52 | preferences.edit().putInt("client_io_mode",mode).apply(); 53 | } 54 | 55 | public int getClientIOMode(){ 56 | return preferences.getInt("client_io_mode", MODE_NORMAL); 57 | } 58 | 59 | public void setConnectServerControllerIp(String ip){ 60 | preferences.edit().putString("connect_server_controller_ip",ip).apply(); 61 | } 62 | 63 | public String getConnectServerControllerIp(){ 64 | return preferences.getString("connect_server_controller_ip",""); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/ConfigDB.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.ContentValues; 5 | import android.content.Context; 6 | import android.database.Cursor; 7 | import android.database.sqlite.SQLiteDatabase; 8 | import android.database.sqlite.SQLiteOpenHelper; 9 | 10 | import androidx.annotation.Nullable; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | import top.weixiansen574.hybridfilexfer.bean.BookMark; 16 | 17 | @SuppressLint("Range") 18 | public class ConfigDB extends SQLiteOpenHelper { 19 | public static final int VERSION = 1; 20 | private static ConfigDB instance; 21 | private ConfigDB(@Nullable Context context) { 22 | super(context, "config", null, VERSION); 23 | } 24 | 25 | public synchronized static ConfigDB getInstance(Context context){ 26 | if (instance == null){ 27 | instance = new ConfigDB(context.getApplicationContext()); 28 | } 29 | return instance; 30 | } 31 | 32 | @Override 33 | public void onCreate(SQLiteDatabase db) { 34 | db.execSQL("CREATE TABLE local_dir_bookmarks (\n" + 35 | " id INTEGER PRIMARY KEY AUTOINCREMENT\n" + 36 | " NOT NULL,\n" + 37 | " path TEXT NOT NULL\n" + 38 | " UNIQUE\n" + 39 | ");"); 40 | db.execSQL("CREATE TABLE remote_dir_bookmarks (\n" + 41 | " id INTEGER PRIMARY KEY AUTOINCREMENT\n" + 42 | " NOT NULL,\n" + 43 | " path TEXT UNIQUE\n" + 44 | " NOT NULL\n" + 45 | ");"); 46 | } 47 | 48 | @Override 49 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 50 | 51 | } 52 | 53 | public long addLocalBookmark(String path) { 54 | ContentValues cv = new ContentValues(); 55 | cv.put("path", path); 56 | return getWritableDatabase() 57 | .insert("local_dir_bookmarks", null, cv); 58 | 59 | } 60 | 61 | public long addRemoteBookmark(String path) { 62 | ContentValues cv = new ContentValues(); 63 | cv.put("path", path); 64 | return getWritableDatabase() 65 | .insert("remote_dir_bookmarks", null, cv); 66 | } 67 | 68 | public boolean checkLocalBookmarkExists(String path) { 69 | Cursor cursor = getReadableDatabase() 70 | .rawQuery("SELECT * FROM local_dir_bookmarks WHERE path = ?", new String[]{path}); 71 | boolean exists = cursor.moveToFirst(); 72 | cursor.close(); 73 | return exists; 74 | } 75 | 76 | public boolean checkRemoteBookmarkExists(String path) { 77 | Cursor cursor = getReadableDatabase() 78 | .rawQuery("SELECT * FROM remote_dir_bookmarks WHERE path = ?", new String[]{path}); 79 | boolean exists = cursor.moveToFirst(); 80 | cursor.close(); 81 | return exists; 82 | } 83 | 84 | 85 | public long removeLocalBookmark(int id) { 86 | return getWritableDatabase() 87 | .delete("local_dir_bookmarks", "id = ?", new String[]{String.valueOf(id)}); 88 | } 89 | 90 | public long removeRemoteBookmark(int id) { 91 | return getWritableDatabase() 92 | .delete("remote_dir_bookmarks", "id = ?", new String[]{String.valueOf(id)}); 93 | } 94 | 95 | 96 | public List getAllLocalBookmark() { 97 | return getAllBookmarks("local_dir_bookmarks"); 98 | } 99 | 100 | public List getAllRemoteBookmark() { 101 | return getAllBookmarks("remote_dir_bookmarks"); 102 | } 103 | 104 | private List getAllBookmarks(String tableName){ 105 | Cursor cursor = getReadableDatabase().rawQuery("SELECT * FROM "+tableName, null); 106 | List bookmarks = new ArrayList<>(cursor.getCount()); 107 | while (cursor.moveToNext()) { 108 | bookmarks.add( 109 | new BookMark( 110 | cursor.getInt(cursor.getColumnIndex("id")), 111 | cursor.getString(cursor.getColumnIndex("path")) 112 | )); 113 | } 114 | cursor.close(); 115 | return bookmarks; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/IOService.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer; 2 | 3 | import android.app.Service; 4 | import android.content.ComponentName; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.os.IBinder; 8 | 9 | import rikka.shizuku.Shizuku; 10 | 11 | public class IOService extends Service { 12 | private IOServiceImpl service; 13 | private static Shizuku.UserServiceArgs userServiceArgs; 14 | public IOService() { 15 | } 16 | 17 | @Override 18 | public IBinder onBind(Intent intent) { 19 | service = new IOServiceImpl(); 20 | return service; 21 | } 22 | 23 | @Override 24 | public void onDestroy() { 25 | service.destroy(); 26 | } 27 | 28 | public static synchronized Shizuku.UserServiceArgs getUserServiceArgs(Context context){ 29 | if (userServiceArgs == null) { 30 | userServiceArgs = new Shizuku.UserServiceArgs(new ComponentName(context, IOServiceImpl.class)) 31 | .daemon(true) 32 | .processNameSuffix("IOService") 33 | .debuggable(false) 34 | .version(1); 35 | } 36 | return userServiceArgs; 37 | } 38 | } -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/NativeMemory.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | /** 6 | * 由于Java层有256M或512M的堆内存大小限制 7 | * ByteBuffer.allocate() 和 ByteBuffer.allocateDirect() 8 | * 都不可以获取共计超过256M或512M的内存。故用JNI分配内存并生成对应ByteBuffer。 9 | */ 10 | public class NativeMemory { 11 | static { 12 | System.loadLibrary("native-memory"); // 加载 JNI 库 13 | } 14 | 15 | public static native ByteBuffer allocateLargeBuffer(int size); 16 | public static native void freeBuffer(ByteBuffer buffer); 17 | } 18 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/NetCardIcon.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer; 2 | 3 | public class NetCardIcon { 4 | public static int matchIdForIName(String iName){ 5 | if (iName.startsWith("wlan")) { 6 | return R.drawable.wifi; 7 | } else if (iName.equals("USB_ADB")) { 8 | return R.drawable.usb; 9 | } else if (iName.startsWith("rndis")) { 10 | return R.drawable.usb; 11 | } else if (iName.startsWith("bt")) { 12 | return R.drawable.bt; 13 | } else if (iName.startsWith("tun")) {//VPN开的虚拟网卡 14 | return R.drawable.ethernet; 15 | } else { 16 | return R.drawable.ethernet; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/aidl/ParcelableRemoteFile.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.aidl; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | import java.io.File; 7 | 8 | import top.weixiansen574.hybridfilexfer.core.bean.RemoteFile; 9 | 10 | public class ParcelableRemoteFile extends RemoteFile implements Parcelable { 11 | protected ParcelableRemoteFile(Parcel in) { 12 | super(in.readString(), in.readString(), in.readLong(), in.readLong(), in.readByte() != 0); 13 | } 14 | 15 | public ParcelableRemoteFile(File file) { 16 | super(file); 17 | } 18 | 19 | @Override 20 | public int describeContents() { 21 | return 0; 22 | } 23 | 24 | @Override 25 | public void writeToParcel(Parcel dest, int flags) { 26 | dest.writeString(this.name); 27 | dest.writeString(this.path); 28 | dest.writeLong(this.lastModified); 29 | dest.writeLong(this.size); 30 | dest.writeByte(this.isDirectory ? (byte) 1 : (byte) 0); 31 | } 32 | 33 | public static final Creator CREATOR = new Creator() { 34 | @Override 35 | public ParcelableRemoteFile createFromParcel(Parcel source) { 36 | return new ParcelableRemoteFile(source); 37 | } 38 | 39 | @Override 40 | public ParcelableRemoteFile[] newArray(int size) { 41 | return new ParcelableRemoteFile[size]; 42 | } 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/bean/BookMark.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.bean; 2 | 3 | public class BookMark { 4 | public final int id; 5 | public final String path; 6 | 7 | public BookMark(int id, String path) { 8 | this.id = id; 9 | this.path = path; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/core/ControllerIdentifiers.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core; 2 | 3 | public class ControllerIdentifiers { 4 | public static final short SHUTDOWN = 0; 5 | public static final short LIST_FILES = 1; 6 | public static final short DELETE_FILE = 2; 7 | public static final short MKDIR = 3; 8 | public static final short REQUEST_RECEIVE = 10; 9 | public static final short REQUEST_SEND = 11; 10 | 11 | //就让魔法打败魔法吧! 12 | /** 13 | * 禁止转载应用到酷安 14 | * 不许未经授权将本项目爬取到国内平台,点名GitCode,除非你的平台容得下下面的数字😁 15 | */ 16 | private static final int 酷安飞机杯 = 8964; 17 | /** 18 | * 你号没了! 19 | * 当然,如果你看到了有人在酷安分享本软件,请拿此内容进行举报攻击,让他狠狠的享受以下内容! 20 | * 你的账号【___】,存在发布涉政信息的违规行为,已禁止访问 21 | */ 22 | private static final String 威武小姐姐 = "学“习”通😋"; 23 | 24 | } -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/core/FileBlock.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core; 2 | 3 | import java.io.File; 4 | import java.nio.ByteBuffer; 5 | 6 | public class FileBlock implements Comparable { 7 | public static final int BLOCK_SIZE = 1024*1024;//1MB 8 | 9 | public final boolean isFile; 10 | public final int fileIndex; 11 | public final String path; 12 | public final long lastModified; 13 | public final long totalSize; 14 | public final int index; 15 | public final ByteBuffer data; 16 | 17 | public FileBlock(boolean isFile, int fileIndex, String path, long lastModified, long totalSize, int index, ByteBuffer data) { 18 | this.isFile = isFile; 19 | this.fileIndex = fileIndex; 20 | this.path = path; 21 | this.lastModified = lastModified; 22 | this.totalSize = totalSize; 23 | this.index = index; 24 | this.data = data; 25 | } 26 | 27 | public long getStartPosition(){ 28 | return BLOCK_SIZE * ((long) index); 29 | } 30 | 31 | public long calcBlockCount(){ 32 | return totalSize / BLOCK_SIZE + 1; 33 | } 34 | 35 | public boolean isFile(){ 36 | return isFile; 37 | } 38 | 39 | public boolean isDirectory(){ 40 | return !isFile; 41 | } 42 | 43 | public int getLength(){ 44 | if (data == null){ 45 | return -1; 46 | } 47 | return data.position(); 48 | } 49 | 50 | @Override 51 | public int compareTo(FileBlock other) { 52 | if (this.fileIndex != other.fileIndex) { 53 | return Integer.compare(this.fileIndex, other.fileIndex); 54 | } 55 | // 如果 nameIndex 相同,比较 index 56 | return Integer.compare(this.index, other.index); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/core/SendFileCall.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core; 2 | 3 | import java.util.concurrent.Callable; 4 | 5 | import top.weixiansen574.hybridfilexfer.core.callback.TransferFileCallback; 6 | import top.weixiansen574.nio.DataByteChannel; 7 | 8 | public class SendFileCall implements Callable { 9 | private final ReadFileCall readFileCall; 10 | private final DataByteChannel channel; 11 | private final TransferConnection connection; 12 | private final TransferFileCallback callback; 13 | 14 | public SendFileCall(ReadFileCall readFileCall, TransferConnection connection, TransferFileCallback callback) { 15 | this.readFileCall = readFileCall; 16 | this.connection = connection; 17 | this.channel = connection.channel; 18 | this.callback = callback; 19 | connection.resetTotalTrafficInfo(); 20 | } 21 | 22 | @Override 23 | public Void call() throws Exception { 24 | FileBlock fileBlock = null; 25 | try { 26 | long startTime = System.currentTimeMillis(); 27 | while (true) { 28 | fileBlock = readFileCall.takeBlock(); 29 | //-1为特殊块 30 | if (fileBlock.fileIndex == -1) { 31 | if (fileBlock == ReadFileCall.END_POINT) { 32 | channel.writeShort(TransferIdentifiers.EOF); 33 | callback.onChannelComplete(connection.iName, 34 | connection.getTotalTraffic().uploadTraffic, 35 | System.currentTimeMillis() - startTime); 36 | } else if (fileBlock == ReadFileCall.INTERRUPT) { 37 | channel.writeShort(TransferIdentifiers.END_OF_INTERRUPTED); 38 | callback.onChannelError(connection.iName,TransferFileCallback.ERROR_TYPE_INTERRUPT, null); 39 | } else if (fileBlock == ReadFileCall.READ_ERROR) { 40 | channel.writeShort(TransferIdentifiers.END_OF_READ_ERROR); 41 | callback.onChannelError(connection.iName,TransferFileCallback.ERROR_TYPE_READ_ERROR, null); 42 | } else if (fileBlock == ReadFileCall.WRITE_ERROR) { 43 | channel.writeShort(TransferIdentifiers.END_OF_WRITE_ERROR); 44 | callback.onChannelError(connection.iName,TransferFileCallback.ERROR_TYPE_WRITE_ERROR, null); 45 | } 46 | break; 47 | } 48 | channel.writeShort(fileBlock.isFile ? TransferIdentifiers.FILE : 49 | TransferIdentifiers.FOLDER);//是否文件夹 50 | channel.writeInt(fileBlock.fileIndex); 51 | channel.writeUTF(fileBlock.path);//路径 52 | channel.writeLong(fileBlock.lastModified);//修改日期 53 | if (!fileBlock.isFile) continue; 54 | channel.writeLong(fileBlock.totalSize);//总大小 55 | channel.writeInt(fileBlock.index);//索引 56 | channel.writeInt(fileBlock.getLength());//单块的长度 57 | 58 | callback.onFileUploading(connection.iName, fileBlock.path, 59 | fileBlock.getStartPosition() + fileBlock.getLength(), 60 | fileBlock.totalSize); 61 | 62 | fileBlock.data.flip(); 63 | channel.write(fileBlock.data); 64 | readFileCall.recycleBuffer(fileBlock.data); 65 | connection.addUploadedBytes(fileBlock.getLength()); 66 | } 67 | } catch (Exception e) { 68 | //若发生异常,通知其他传输通道,停止传输 69 | if (fileBlock != null){ 70 | //回收文件分块的ByteBuffer,否则导致这个Buffer免费了 71 | readFileCall.recycleBuffer(fileBlock.data); 72 | } 73 | readFileCall.shutdownByConnectionBreak(); 74 | callback.onChannelError(connection.iName,TransferFileCallback.ERROR_TYPE_EXCEPTION, e.toString()); 75 | throw e; 76 | } 77 | return null; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/core/SpeedMonitorThread.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import top.weixiansen574.hybridfilexfer.core.TransferConnection; 7 | import top.weixiansen574.hybridfilexfer.core.bean.TrafficInfo; 8 | import top.weixiansen574.hybridfilexfer.core.callback.TransferFileCallback; 9 | 10 | public class SpeedMonitorThread extends Thread { 11 | private boolean isRun = true; 12 | private final List connections; 13 | private final TransferFileCallback callback; 14 | 15 | public SpeedMonitorThread(List connections, TransferFileCallback callback) { 16 | this.connections = connections; 17 | this.callback = callback; 18 | } 19 | 20 | @Override 21 | @SuppressWarnings("BusyWait") 22 | public void run() { 23 | while (isRun){ 24 | try { 25 | Thread.sleep(1000); 26 | } catch (InterruptedException e) { 27 | break; 28 | } 29 | List trafficInfoList = new ArrayList<>(); 30 | for (TransferConnection channel : connections) { 31 | trafficInfoList.add(channel.resetCurrentTrafficInfo()); 32 | } 33 | callback.onSpeedInfo(trafficInfoList); 34 | } 35 | } 36 | 37 | public void cancel(){ 38 | isRun = false; 39 | interrupt(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/core/TransferConnection.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core; 2 | 3 | import java.io.IOException; 4 | 5 | import top.weixiansen574.hybridfilexfer.core.bean.TrafficInfo; 6 | import top.weixiansen574.nio.DataByteChannel; 7 | 8 | public class TransferConnection { 9 | public final String iName; 10 | private TrafficInfo currentTraffic; 11 | private TrafficInfo totalTraffic; 12 | public final DataByteChannel channel; 13 | 14 | public TransferConnection(String iName, DataByteChannel channel) throws IOException { 15 | this.iName = iName; 16 | this.channel = channel; 17 | currentTraffic = new TrafficInfo(); 18 | totalTraffic = new TrafficInfo(); 19 | } 20 | 21 | public synchronized void addUploadedBytes(long byteCount) { 22 | currentTraffic.uploadTraffic += byteCount; 23 | totalTraffic.uploadTraffic += byteCount; 24 | } 25 | 26 | public synchronized void addDownloadedBytes(long byteCount) { 27 | currentTraffic.downloadTraffic += byteCount; 28 | totalTraffic.downloadTraffic += byteCount; 29 | } 30 | 31 | public synchronized TrafficInfo resetCurrentTrafficInfo() { 32 | TrafficInfo info = currentTraffic; 33 | currentTraffic = new TrafficInfo(iName); 34 | return info; 35 | } 36 | 37 | public synchronized TrafficInfo resetTotalTrafficInfo() { 38 | TrafficInfo info = totalTraffic; 39 | totalTraffic = new TrafficInfo(iName); 40 | return info; 41 | } 42 | 43 | public synchronized TrafficInfo getTotalTraffic(){ 44 | return totalTraffic; 45 | } 46 | 47 | public void close() throws IOException { 48 | channel.close(); 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/core/TransferIdentifiers.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core; 2 | 3 | public class TransferIdentifiers { 4 | public static final short END_POINT = -1; 5 | public static final short FILE = 0; 6 | public static final short FOLDER = 1; 7 | public static final short FILE_SLICE = 2; 8 | public static final short EOF = 3; 9 | public static final short END_OF_INTERRUPTED = 4; 10 | public static final short END_OF_READ_ERROR = 5; 11 | public static final short END_OF_WRITE_ERROR = 6; 12 | } 13 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/core/Utils.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core; 2 | 3 | import java.io.File; 4 | import java.text.SimpleDateFormat; 5 | import java.util.ArrayList; 6 | import java.util.Date; 7 | import java.util.List; 8 | import java.util.Locale; 9 | 10 | import top.weixiansen574.hybridfilexfer.core.bean.RemoteFile; 11 | 12 | public class Utils { 13 | public static final String ILLEGAL_CHARACTERS = "<>:\"/\\|?*"; 14 | 15 | public static void sortFiles(List fileList) { 16 | // 使用Comparator自定义比较规则 17 | fileList.sort((f1, f2) -> { 18 | // 文件夹优先于文件 19 | if (f1.isDirectory() && !f2.isDirectory()) { 20 | return -1; 21 | } else if (!f1.isDirectory() && f2.isDirectory()) { 22 | return 1; 23 | } else { 24 | // 如果类型相同,则按名称排序 25 | return f1.getName().compareTo(f2.getName()); 26 | } 27 | }); 28 | } 29 | 30 | public static String formatSpeed(long bytesPerSecond) { 31 | if (bytesPerSecond < 1024) { 32 | return bytesPerSecond + "B/s"; 33 | } 34 | if (bytesPerSecond < 1024 * 1024) { 35 | return String.format(Locale.getDefault(), "%.2fKB/s", bytesPerSecond / 1024.0); 36 | } 37 | return String.format(Locale.getDefault(), "%.2fMB/s", bytesPerSecond / (1024.0 * 1024.0)); 38 | } 39 | 40 | public static String formatDateTime(long milliseconds) { 41 | //格式化为年-月-日 时:分 42 | return new SimpleDateFormat("yy-MM-dd HH:mm", Locale.getDefault()).format(new Date(milliseconds)); 43 | } 44 | 45 | /** 46 | * 格式化毫秒数为指定的时间格式。 47 | * 48 | * @param milliseconds 输入的毫秒数 49 | * @return 格式化后的时间字符串 50 | */ 51 | public static String formatTime(long milliseconds) { 52 | if (milliseconds < 0) { 53 | throw new IllegalArgumentException("毫秒数不能为负数"); 54 | } 55 | 56 | if (milliseconds < 1000) { 57 | return milliseconds + "ms"; 58 | } 59 | 60 | long totalSeconds = milliseconds / 1000; 61 | long hours = totalSeconds / 3600; 62 | long minutes = (totalSeconds % 3600) / 60; 63 | long seconds = totalSeconds % 60; 64 | 65 | if (hours == 0) { 66 | return String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds); 67 | } else { 68 | return String.format(Locale.getDefault(), "%02d:%02d:%02d", hours, minutes, seconds); 69 | } 70 | } 71 | 72 | public static String formatFileSize(long size) { 73 | if (size < 1024) { 74 | return size + "B"; 75 | } 76 | if (size < 1024 * 1024) { 77 | return String.format(Locale.getDefault(), "%.2fKB", size / 1024.0); 78 | } 79 | if (size < 1024 * 1024 * 1024) { 80 | return String.format(Locale.getDefault(), "%.2fMB", size / (1024.0 * 1024.0)); 81 | } 82 | return String.format(Locale.getDefault(), "%.2fGB", size / (1024.0 * 1024.0 * 1024.0)); 83 | } 84 | 85 | public static boolean containsIllegalCharacters(String text) { 86 | for (char c : ILLEGAL_CHARACTERS.toCharArray()) { 87 | if (text.indexOf(c) >= 0) { 88 | return true; // 如果找到非法字符,返回 true 89 | } 90 | } 91 | return false; // 如果没有找到非法字符,返回 false 92 | } 93 | 94 | public static List listRemoteFiles(String path){ 95 | File[] files = new File(path).listFiles(); 96 | if (files == null) { 97 | return null; 98 | } 99 | ArrayList remoteFiles = new ArrayList<>(files.length); 100 | for (File file : files) { 101 | remoteFiles.add(new RemoteFile(file)); 102 | } 103 | return remoteFiles; 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/core/bean/RemoteFile.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core.bean; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | import java.io.File; 6 | 7 | public class RemoteFile { 8 | protected final String name; 9 | protected final String path; 10 | protected final long lastModified; 11 | protected final long size; 12 | protected final boolean isDirectory; 13 | //public final String name; 14 | //public final String path; 15 | //public final long lastModified; 16 | //public final long size; 17 | //public final boolean isDirectory; 18 | 19 | public RemoteFile(File file) { 20 | this.path = file.getPath(); 21 | this.isDirectory = file.isDirectory(); 22 | this.name = file.getName(); 23 | this.lastModified = file.lastModified(); 24 | this.size = file.length(); 25 | } 26 | 27 | public RemoteFile(String name, String path, long lastModified, long size, boolean isDirectory){ 28 | this.name = name; 29 | this.path = path; 30 | this.lastModified = lastModified; 31 | this.size = size; 32 | this.isDirectory = isDirectory; 33 | } 34 | 35 | public RemoteFile(RemoteFile file){ 36 | this.name = file.name; 37 | this.path = file.path; 38 | this.lastModified = file.lastModified; 39 | this.size = file.size; 40 | this.isDirectory = file.isDirectory; 41 | } 42 | 43 | 44 | @NotNull 45 | @Override 46 | public String toString() { 47 | return "RemoteFile{" + 48 | "path='" + path + '\'' + 49 | ", isDirectory=" + isDirectory + 50 | '}'; 51 | } 52 | 53 | public String getPath() { 54 | return path; 55 | } 56 | 57 | public boolean isDirectory() { 58 | return isDirectory; 59 | } 60 | 61 | public String getName() { 62 | return name; 63 | } 64 | 65 | public long lastModified() { 66 | return lastModified; 67 | } 68 | 69 | public long getSize() { 70 | return size; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/core/bean/ServerNetInterface.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core.bean; 2 | 3 | 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.net.InetAddress; 7 | 8 | public class ServerNetInterface{ 9 | public final String name; 10 | public final InetAddress address; 11 | public final InetAddress clientBindAddress; 12 | 13 | public ServerNetInterface(String name, InetAddress address, InetAddress clientBindAddress) { 14 | this.name = name; 15 | this.address = address; 16 | this.clientBindAddress = clientBindAddress; 17 | } 18 | 19 | 20 | @NotNull 21 | @Override 22 | public String toString() { 23 | return "ServerNetInterface{" + 24 | "name='" + name + '\'' + 25 | ", address=" + address + 26 | ", clientBindAddress=" + clientBindAddress + 27 | '}'; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/core/bean/TrafficInfo.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core.bean; 2 | 3 | public class TrafficInfo { 4 | public String iName; 5 | public long uploadTraffic; 6 | public long downloadTraffic; 7 | 8 | public TrafficInfo(String iName, long uploadTraffic, long downloadTraffic) { 9 | this.iName = iName; 10 | this.uploadTraffic = uploadTraffic; 11 | this.downloadTraffic = downloadTraffic; 12 | } 13 | public TrafficInfo() { 14 | } 15 | public TrafficInfo(String iName) { 16 | this.iName = iName; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/core/callback/ClientCallBack.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core.callback; 2 | 3 | public interface ClientCallBack extends TransferFileCallback { 4 | void onReceiving(); 5 | void onSending(); 6 | void onExit(); 7 | } 8 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/core/callback/ConnectServerCallback.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core.callback; 2 | 3 | import java.net.InetAddress; 4 | import java.util.List; 5 | 6 | public interface ConnectServerCallback { 7 | void onConnectingControlChannel(String address, int port); 8 | 9 | void onVersionMismatch(int localVersion, int remoteVersion); 10 | 11 | void onConnectControlFailed(); 12 | 13 | void onConnectingTransferChannel( 14 | String name, 15 | InetAddress inetAddress, 16 | InetAddress bindAddress); 17 | 18 | void onConnectTransferChannelFailed(String name, InetAddress inetAddress, Exception e); 19 | 20 | void onOOM( 21 | int createdBuffers, 22 | int requiredBuffers, 23 | long maxMemoryMB, 24 | String osArch); 25 | 26 | void onRemoteOOM(); 27 | 28 | void onConnectSuccess(List channelNames); 29 | } 30 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/core/callback/TransferFileCallback.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core.callback; 2 | 3 | import java.util.List; 4 | 5 | import top.weixiansen574.hybridfilexfer.core.bean.TrafficInfo; 6 | 7 | public interface TransferFileCallback { 8 | int ERROR_TYPE_EXCEPTION = 1; 9 | int ERROR_TYPE_INTERRUPT = 2; 10 | int ERROR_TYPE_READ_ERROR = 3; 11 | int ERROR_TYPE_WRITE_ERROR = 4; 12 | 13 | void onFileUploading(String iName, String path, long targetSize, long totalSize); 14 | 15 | void onFileDownloading(String iName, String path, long targetSize, long totalSize); 16 | 17 | void onSpeedInfo(List trafficInfoList); 18 | 19 | void onChannelComplete(String iName, long traffic, long time); 20 | 21 | void onChannelError(String iName, int errorType, String message);//异常信息 or 断开 22 | 23 | void onReadFileError(String message); 24 | 25 | void onWriteFileError(String message); 26 | 27 | void onComplete(boolean isUpload,long traffic, long time); 28 | 29 | //传输通道有其中一个断开时 30 | void onIncomplete(); 31 | 32 | } 33 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/droidcore/DisconnectTask.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.droidcore; 2 | 3 | import java.io.IOException; 4 | import java.nio.ByteBuffer; 5 | 6 | import top.weixiansen574.async.BackstageTask; 7 | import top.weixiansen574.hybridfilexfer.NativeMemory; 8 | import top.weixiansen574.hybridfilexfer.core.ControllerIdentifiers; 9 | import top.weixiansen574.hybridfilexfer.core.TransferConnection; 10 | 11 | public class DisconnectTask extends BackstageTask { 12 | private final HFXServer server; 13 | public DisconnectTask(BaseEventHandler uiHandler, HFXServer server) { 14 | super(uiHandler); 15 | this.server = server; 16 | } 17 | 18 | @Override 19 | protected void onStart(BaseEventHandler eventHandlerProxy) throws Throwable { 20 | server.disconnect(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/droidcore/DroidHFXClient.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.droidcore; 2 | 3 | import android.app.ActivityManager; 4 | import android.content.Context; 5 | 6 | import java.nio.ByteBuffer; 7 | import java.util.List; 8 | import java.util.concurrent.LinkedBlockingDeque; 9 | 10 | import top.weixiansen574.hybridfilexfer.NativeMemory; 11 | import top.weixiansen574.hybridfilexfer.aidl.IIOService; 12 | import top.weixiansen574.hybridfilexfer.core.HFXClient; 13 | import top.weixiansen574.hybridfilexfer.core.ReadFileCall; 14 | import top.weixiansen574.hybridfilexfer.core.WriteFileCall; 15 | import top.weixiansen574.hybridfilexfer.core.bean.Directory; 16 | import top.weixiansen574.hybridfilexfer.core.bean.RemoteFile; 17 | 18 | public class DroidHFXClient extends HFXClient { 19 | private final IIOService iioService; 20 | private final Context context; 21 | public DroidHFXClient(String serverControllerAddress, int serverPort,String homeDir, IIOService iioService, Context context) { 22 | super(serverControllerAddress, serverPort,homeDir); 23 | this.iioService = iioService; 24 | this.context = context; 25 | } 26 | 27 | @Override 28 | public ByteBuffer createBuffer(int size) { 29 | return NativeMemory.allocateLargeBuffer(size); 30 | } 31 | 32 | @Override 33 | public long getAvailableMemoryMB() { 34 | ActivityManager activityManager = context.getSystemService(ActivityManager.class); 35 | ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); 36 | activityManager.getMemoryInfo(memoryInfo); 37 | 38 | long totalMemory = memoryInfo.totalMem; 39 | 40 | long availableMemory = memoryInfo.availMem; 41 | 42 | long totalMemoryMB = totalMemory / (1024 * 1024); 43 | long availableMemoryMB = availableMemory / (1024 * 1024); 44 | 45 | return (long) (availableMemoryMB - (totalMemoryMB * 0.05)); 46 | } 47 | 48 | @Override 49 | protected boolean deleteLocalFile(String path) throws Exception { 50 | return iioService.deleteFile(path); 51 | } 52 | 53 | @Override 54 | protected boolean mkdir(String parent, String child) throws Exception { 55 | return iioService.appendAndMkdirs(parent,child); 56 | } 57 | 58 | @Override 59 | protected List listFiles(String path) throws Exception { 60 | return HFXServer.listLocalFiles(iioService,path); 61 | } 62 | 63 | @Override 64 | protected WriteFileCall createWriteFileCall(LinkedBlockingDeque buffers, int dequeCount) { 65 | return new DroidWriteFileCall(buffers,dequeCount,iioService); 66 | } 67 | 68 | @Override 69 | protected ReadFileCall createReadFileCall(LinkedBlockingDeque buffers, List files, Directory localDir, Directory remoteDir, int operateThreadCount) { 70 | return new DroidReadFileCall(iioService,buffers,files,localDir,remoteDir,operateThreadCount); 71 | } 72 | 73 | public void freeBuffers(){ 74 | for (ByteBuffer buffer : buffers) { 75 | NativeMemory.freeBuffer(buffer); 76 | } 77 | buffers.clear(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/droidcore/DroidReadFileCall.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.droidcore; 2 | 3 | import android.os.ParcelFileDescriptor; 4 | 5 | import java.io.FileInputStream; 6 | import java.nio.ByteBuffer; 7 | import java.nio.channels.FileChannel; 8 | import java.util.List; 9 | import java.util.concurrent.LinkedBlockingDeque; 10 | 11 | import top.weixiansen574.hybridfilexfer.aidl.IIOService; 12 | import top.weixiansen574.hybridfilexfer.core.ReadFileCall; 13 | import top.weixiansen574.hybridfilexfer.core.bean.Directory; 14 | import top.weixiansen574.hybridfilexfer.core.bean.RemoteFile; 15 | 16 | public class DroidReadFileCall extends ReadFileCall { 17 | private final IIOService ioService; 18 | 19 | private ParcelFileDescriptor pfd; 20 | private FileInputStream fileInputStream; 21 | private FileChannel channel; 22 | 23 | public DroidReadFileCall(IIOService ioService,LinkedBlockingDeque buffers, List files, Directory localDir, Directory remoteDir, int operateThreadCount) { 24 | super(buffers, files, localDir, remoteDir, operateThreadCount); 25 | this.ioService = ioService; 26 | } 27 | 28 | @Override 29 | protected boolean fileExists(String path) throws Exception { 30 | return ioService.fileExists(path); 31 | } 32 | 33 | @Override 34 | protected List listFiles(String path) throws Exception { 35 | return HFXServer.listLocalFiles(ioService,path); 36 | } 37 | 38 | @Override 39 | protected FileChannel openFile(String path) throws Exception { 40 | pfd = ioService.openReadableFile(path); 41 | fileInputStream = new FileInputStream(pfd.getFileDescriptor()); 42 | channel = fileInputStream.getChannel(); 43 | return channel; 44 | } 45 | 46 | @Override 47 | protected void closeFile() throws Exception { 48 | channel.close(); 49 | fileInputStream.close(); 50 | pfd.close(); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/droidcore/DroidWriteFileCall.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.droidcore; 2 | 3 | import android.os.ParcelFileDescriptor; 4 | 5 | import java.io.FileOutputStream; 6 | import java.io.IOException; 7 | import java.nio.ByteBuffer; 8 | import java.nio.channels.FileChannel; 9 | import java.util.concurrent.LinkedBlockingDeque; 10 | 11 | import top.weixiansen574.hybridfilexfer.aidl.IIOService; 12 | import top.weixiansen574.hybridfilexfer.core.WriteFileCall; 13 | 14 | public class DroidWriteFileCall extends WriteFileCall { 15 | private final IIOService ioService; 16 | private ParcelFileDescriptor pfd; 17 | private FileOutputStream fileOutputStream; 18 | private FileChannel channel; 19 | public DroidWriteFileCall(LinkedBlockingDeque buffers, int dequeCount, IIOService ioService) { 20 | super(buffers, dequeCount); 21 | this.ioService = ioService; 22 | } 23 | 24 | @Override 25 | protected void createParentDirIfNotExists(String path) throws Exception { 26 | String exception = ioService.createParentDirIfNotExists(path); 27 | if (exception != null){ 28 | throw new IOException(exception); 29 | } 30 | } 31 | 32 | @Override 33 | protected void tryMkdirs(String path) throws Exception { 34 | String exception = ioService.tryMkdirs(path); 35 | if (exception != null){ 36 | throw new IOException(exception); 37 | } 38 | } 39 | 40 | @Override 41 | protected FileChannel createAndOpenFile(String path, long length) throws Exception { 42 | pfd = ioService.createAndOpenWriteableFile(path, length); 43 | fileOutputStream = new FileOutputStream(pfd.getFileDescriptor()); 44 | channel = fileOutputStream.getChannel(); 45 | return channel; 46 | } 47 | 48 | @Override 49 | protected void closeFile() throws Exception { 50 | channel.close(); 51 | fileOutputStream.close(); 52 | pfd.close(); 53 | } 54 | 55 | @Override 56 | protected boolean setFileLastModified(String path, long time) throws Exception { 57 | return ioService.setFileLastModified(path,time); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/droidcore/StartServerTask.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.droidcore; 2 | 3 | import java.io.IOException; 4 | import java.net.InetSocketAddress; 5 | import java.nio.ByteBuffer; 6 | import java.nio.channels.ServerSocketChannel; 7 | import java.nio.charset.StandardCharsets; 8 | import java.util.ArrayList; 9 | import java.util.Arrays; 10 | import java.util.List; 11 | import java.util.concurrent.LinkedBlockingDeque; 12 | 13 | import top.weixiansen574.async.BackstageTask; 14 | import top.weixiansen574.hybridfilexfer.NativeMemory; 15 | import top.weixiansen574.hybridfilexfer.core.FileBlock; 16 | import top.weixiansen574.hybridfilexfer.core.TransferConnection; 17 | import top.weixiansen574.hybridfilexfer.core.bean.ServerNetInterface; 18 | import top.weixiansen574.hybridfilexfer.droidcore.callback.StartServerCallback; 19 | import top.weixiansen574.nio.DataByteChannel; 20 | 21 | public class StartServerTask extends BackstageTask { 22 | private final HFXServer server; 23 | private final int port; 24 | private final List interfaceList; 25 | private final int localBufferCount; 26 | private final int remoteBufferCount; 27 | 28 | public StartServerTask(StartServerCallback uiHandler, HFXServer server, int port, List interfaceList, int localBufferCount, int remoteBufferCount) { 29 | super(uiHandler); 30 | this.server = server; 31 | this.port = port; 32 | this.interfaceList = interfaceList; 33 | this.localBufferCount = localBufferCount; 34 | this.remoteBufferCount = remoteBufferCount; 35 | } 36 | 37 | @Override 38 | protected void onStart(StartServerCallback callback) throws Throwable { 39 | server.startServer(port,interfaceList,localBufferCount,remoteBufferCount,callback); 40 | } 41 | 42 | @Override 43 | protected void onError(Throwable th) { 44 | server.close(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/droidcore/callback/StartServerCallback.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.droidcore.callback; 2 | 3 | import top.weixiansen574.async.BackstageTask; 4 | 5 | public interface StartServerCallback extends BackstageTask.BaseEventHandler { 6 | void onBindFailed(int port); 7 | void onStatedServer(); 8 | void onAccepted(String name); 9 | void onAcceptFailed(String name); 10 | void onPcOOM(); 11 | void onMeOOM(int created, int localBufferCount); 12 | void onConnectSuccess(); 13 | } 14 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/listadapter/BookmarkAdapter.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.listadapter; 2 | 3 | import android.app.AlertDialog; 4 | import android.content.Context; 5 | import android.content.DialogInterface; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.TextView; 10 | import android.widget.Toast; 11 | 12 | import androidx.annotation.NonNull; 13 | import androidx.recyclerview.widget.RecyclerView; 14 | 15 | import java.util.List; 16 | 17 | import top.weixiansen574.hybridfilexfer.ConfigDB; 18 | import top.weixiansen574.hybridfilexfer.R; 19 | import top.weixiansen574.hybridfilexfer.bean.BookMark; 20 | 21 | 22 | public class BookmarkAdapter extends RecyclerView.Adapter { 23 | protected Context context; 24 | protected DialogInterface dialog; 25 | protected FileSelectAdapter adapter; 26 | protected List bookMarks; 27 | protected final ConfigDB db; 28 | protected final boolean isRemote; 29 | 30 | public BookmarkAdapter(Context context, DialogInterface dialog, FileSelectAdapter adapter,boolean isRemote) { 31 | this.context = context; 32 | this.dialog = dialog; 33 | this.adapter = adapter; 34 | this.db = ConfigDB.getInstance(context); 35 | this.isRemote = isRemote; 36 | if (isRemote){ 37 | bookMarks = db.getAllRemoteBookmark(); 38 | } else { 39 | bookMarks = db.getAllLocalBookmark(); 40 | } 41 | } 42 | 43 | @NonNull 44 | @Override 45 | public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 46 | return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.item_bookmark, parent, false)); 47 | } 48 | 49 | @Override 50 | public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { 51 | BookMark item = bookMarks.get(position); 52 | holder.fileName.setText(item.path); 53 | holder.itemView.setOnClickListener(v -> { 54 | adapter.jump(item.path); 55 | dialog.dismiss(); 56 | }); 57 | holder.itemView.setOnLongClickListener(v -> { 58 | new AlertDialog.Builder(context) 59 | .setTitle(R.string.confirm_delete) 60 | .setMessage(context.getString(R.string.delete_the_bookmark,item.path)) 61 | .setNegativeButton(R.string.cancel, null) 62 | .setPositiveButton(R.string.ok, (dialog, which) -> { 63 | if (onDelete(item)) { 64 | Toast.makeText(context, R.string.deleted_successfully, Toast.LENGTH_SHORT).show(); 65 | bookMarks.remove(item); 66 | notifyItemRemoved(holder.getAdapterPosition()); 67 | } else { 68 | Toast.makeText(context, R.string.deletion_failed, Toast.LENGTH_SHORT).show(); 69 | } 70 | }) 71 | .show(); 72 | return true; 73 | }); 74 | } 75 | 76 | @Override 77 | public int getItemCount() { 78 | return bookMarks.size(); 79 | } 80 | 81 | private boolean onDelete(BookMark bookMark){ 82 | if (isRemote){ 83 | return db.removeRemoteBookmark(bookMark.id) > 0; 84 | } else { 85 | return db.removeLocalBookmark(bookMark.id) > 0; 86 | } 87 | } 88 | 89 | public static class MyViewHolder extends RecyclerView.ViewHolder { 90 | TextView fileName; 91 | public MyViewHolder(@NonNull View itemView) { 92 | super(itemView); 93 | fileName = itemView.findViewById(R.id.file_name); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/listadapter/LocalFileSelectAdapter.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.listadapter; 2 | 3 | import android.app.Activity; 4 | import android.os.Environment; 5 | import android.os.RemoteException; 6 | import android.view.View; 7 | import android.widget.Toast; 8 | 9 | import androidx.appcompat.widget.Toolbar; 10 | import androidx.recyclerview.widget.LinearLayoutManager; 11 | import androidx.recyclerview.widget.RecyclerView; 12 | 13 | import java.util.List; 14 | 15 | import top.weixiansen574.hybridfilexfer.R; 16 | import top.weixiansen574.hybridfilexfer.core.bean.Directory; 17 | import top.weixiansen574.hybridfilexfer.core.bean.RemoteFile; 18 | import top.weixiansen574.hybridfilexfer.droidcore.HFXServer; 19 | 20 | public class LocalFileSelectAdapter extends FileSelectAdapter { 21 | public LocalFileSelectAdapter(Activity context, View loadingView, RecyclerView recyclerView, LinearLayoutManager 22 | linearLayoutManager, Toolbar fileSelectToolbar, View.OnTouchListener onTouchListener, HFXServer server) { 23 | super(context, loadingView, recyclerView, linearLayoutManager, fileSelectToolbar, onTouchListener, server); 24 | } 25 | 26 | @Override 27 | public List listFiles(String path) throws RemoteException { 28 | return server.listLocalFiles(path); 29 | } 30 | 31 | @Override 32 | protected void handleListException(Throwable th) { 33 | 34 | } 35 | 36 | @Override 37 | protected String getDefaultDir(HFXServer server) { 38 | //return "/storage/emulated/0/"; 39 | //改用方法获取内置存储目录,部分安卓设备的内部可能不是/storage/emulated/0/,导致读取目录失败 40 | String path = Environment.getExternalStorageDirectory().getAbsolutePath(); 41 | System.out.println("ExternalStorageDirectory:"+path); 42 | return path; 43 | } 44 | 45 | @Override 46 | protected int getFileSystem(HFXServer server) { 47 | return Directory.getCurrentFileSystem(); 48 | } 49 | 50 | 51 | @Override 52 | public boolean deleteFile(String file) throws RemoteException { 53 | return server.deleteLocalFile(file); 54 | } 55 | 56 | @Override 57 | public void mkdir(String parent, String child) { 58 | try { 59 | if (server.createLocalDir(parent,child)) { 60 | Toast.makeText(context, R.string.chuang_jian_cheng_gong, Toast.LENGTH_SHORT).show(); 61 | refresh(); 62 | } else { 63 | Toast.makeText(context, R.string.chuang_jian_shi_bai, Toast.LENGTH_SHORT).show(); 64 | } 65 | } catch (RemoteException e) { 66 | throw new RuntimeException(e); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/listadapter/RemoteFileSelectAdapter.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.listadapter; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.view.View; 6 | import android.widget.Toast; 7 | 8 | import androidx.appcompat.widget.Toolbar; 9 | import androidx.recyclerview.widget.LinearLayoutManager; 10 | import androidx.recyclerview.widget.RecyclerView; 11 | 12 | import java.io.IOException; 13 | import java.util.List; 14 | 15 | import top.weixiansen574.hybridfilexfer.MainActivity; 16 | import top.weixiansen574.hybridfilexfer.core.bean.RemoteFile; 17 | import top.weixiansen574.hybridfilexfer.R; 18 | import top.weixiansen574.hybridfilexfer.droidcore.HFXServer; 19 | 20 | public class RemoteFileSelectAdapter extends FileSelectAdapter { 21 | 22 | public RemoteFileSelectAdapter(Activity context, View loadingView, RecyclerView recyclerView, LinearLayoutManager 23 | linearLayoutManager, Toolbar fileSelectToolbar, View.OnTouchListener onTouchListener, HFXServer server) { 24 | super(context, loadingView, recyclerView, linearLayoutManager, fileSelectToolbar, onTouchListener, server); 25 | } 26 | 27 | @Override 28 | public List listFiles(String path) throws IOException { 29 | return server.listClientFiles(path); 30 | } 31 | 32 | @Override 33 | protected void handleListException(Throwable th) { 34 | onConnectionLost(); 35 | } 36 | 37 | @Override 38 | protected String getDefaultDir(HFXServer server) { 39 | return server.getRemoteHomeDir(); 40 | } 41 | 42 | @Override 43 | protected int getFileSystem(HFXServer server) { 44 | return server.getRemoteFileSystem(); 45 | } 46 | 47 | 48 | @Override 49 | public boolean deleteFile(String file) throws IOException { 50 | return server.deleteRemoteFile(file); 51 | } 52 | 53 | @Override 54 | public void mkdir(String parent, String child) { 55 | new Thread(() -> { 56 | try { 57 | boolean success = server.createRemoteDir(parent, child); 58 | context.runOnUiThread(() -> { 59 | if (success) { 60 | Toast.makeText(context, R.string.chuang_jian_cheng_gong, Toast.LENGTH_SHORT).show(); 61 | refresh(); 62 | } else { 63 | Toast.makeText(context, R.string.chuang_jian_shi_bai, Toast.LENGTH_SHORT).show(); 64 | } 65 | }); 66 | } catch (IOException e) { 67 | onConnectionLost(); 68 | } 69 | }).start(); 70 | } 71 | 72 | private void onConnectionLost() { 73 | context.setResult(MainActivity.RESULT_CODE_SERVER_DISCONNECT); 74 | new AlertDialog.Builder(context) 75 | .setTitle(R.string.chuang_jian_shi_bai) 76 | .setMessage(R.string.kong_tong_dao_de_lian_jie_yi_duan_kai__) 77 | .setCancelable(false) 78 | .setPositiveButton(R.string.ok, (dialog, which) -> context.finish()).show(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/tasks/BTransferFileCallback.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.tasks; 2 | 3 | import top.weixiansen574.async.BackstageTask; 4 | import top.weixiansen574.hybridfilexfer.core.callback.TransferFileCallback; 5 | 6 | public interface BTransferFileCallback extends BackstageTask.BaseEventHandler, TransferFileCallback { 7 | } 8 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/tasks/ClientTask.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.tasks; 2 | 3 | import top.weixiansen574.async.BackstageTask; 4 | import top.weixiansen574.hybridfilexfer.core.callback.ClientCallBack; 5 | import top.weixiansen574.hybridfilexfer.droidcore.DroidHFXClient; 6 | 7 | public class ClientTask extends BackstageTask { 8 | private final DroidHFXClient client; 9 | 10 | public ClientTask(Callback uiHandler, DroidHFXClient client) { 11 | super(uiHandler); 12 | this.client = client; 13 | } 14 | 15 | @Override 16 | protected void onStart(Callback eventHandlerProxy) throws Throwable { 17 | client.start(eventHandlerProxy); 18 | } 19 | 20 | public interface Callback extends ClientCallBack,BackstageTask.BaseEventHandler{} 21 | } 22 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/tasks/ConnectServerTask.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.tasks; 2 | 3 | import top.weixiansen574.async.BackstageTask; 4 | import top.weixiansen574.hybridfilexfer.core.HFXClient; 5 | import top.weixiansen574.hybridfilexfer.core.callback.ConnectServerCallback; 6 | import top.weixiansen574.hybridfilexfer.droidcore.DroidHFXClient; 7 | 8 | public class ConnectServerTask extends BackstageTask { 9 | private final DroidHFXClient client; 10 | public ConnectServerTask(Callback uiHandler, DroidHFXClient client) { 11 | super(uiHandler); 12 | this.client = client; 13 | } 14 | 15 | @Override 16 | protected void onStart(Callback callback) throws Throwable { 17 | if (!client.connect(callback)) { 18 | client.freeBuffers(); 19 | } 20 | } 21 | 22 | @Override 23 | protected void onError(Throwable th) { 24 | client.freeBuffers(); 25 | } 26 | 27 | public interface Callback extends ConnectServerCallback,BackstageTask.BaseEventHandler{ 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/tasks/DeleteFilesTask.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.tasks; 2 | 3 | import java.util.List; 4 | 5 | import top.weixiansen574.async.BackstageTask; 6 | import top.weixiansen574.hybridfilexfer.listadapter.FileSelectAdapter; 7 | 8 | public class DeleteFilesTask extends BackstageTask { 9 | 10 | final FileSelectAdapter adapter; 11 | final List files; 12 | 13 | public DeleteFilesTask(EventHandler uiHandler, FileSelectAdapter adapter, List files) { 14 | super(uiHandler); 15 | this.adapter = adapter; 16 | this.files = files; 17 | } 18 | 19 | @Override 20 | protected void onStart(EventHandler handler) throws Throwable { 21 | for (int i = 0; i < files.size(); i++) { 22 | String file = files.get(i); 23 | handler.onDeleting(i,file); 24 | if (!adapter.deleteFile(file)){ 25 | handler.onFailed(i,file); 26 | return; 27 | } 28 | } 29 | handler.onSuccess(); 30 | } 31 | 32 | public interface EventHandler extends BackstageTask.BaseEventHandler{ 33 | void onDeleting(int index,String file); 34 | void onFailed(int index,String file); 35 | void onSuccess(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/tasks/ListFilesTask.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.tasks; 2 | 3 | import java.util.List; 4 | 5 | import top.weixiansen574.async.BackstageTask; 6 | import top.weixiansen574.hybridfilexfer.core.Utils; 7 | import top.weixiansen574.hybridfilexfer.core.bean.RemoteFile; 8 | import top.weixiansen574.hybridfilexfer.listadapter.FileSelectAdapter; 9 | 10 | public class ListFilesTask extends BackstageTask { 11 | 12 | public final String path; 13 | public final FileSelectAdapter adapter; 14 | 15 | public ListFilesTask(CallBack uiHandler, String path, FileSelectAdapter adapter) { 16 | super(uiHandler); 17 | this.path = path; 18 | this.adapter = adapter; 19 | } 20 | 21 | @Override 22 | protected void onStart(CallBack eventHandlerProxy) throws Throwable { 23 | List listFiles = adapter.listFiles(path); 24 | if (listFiles != null) { 25 | Utils.sortFiles(listFiles); 26 | listFiles.add(0,new RemoteFile("..", "", 0, 0, true)); 27 | eventHandlerProxy.onResult(listFiles); 28 | } else { 29 | eventHandlerProxy.onResult(null); 30 | } 31 | } 32 | 33 | public interface CallBack extends BackstageTask.BaseEventHandler{ 34 | void onResult(List files); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/tasks/SendFilesToRemoteTask.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.tasks; 2 | 3 | import java.util.List; 4 | 5 | import top.weixiansen574.async.BackstageTask; 6 | import top.weixiansen574.hybridfilexfer.core.bean.Directory; 7 | import top.weixiansen574.hybridfilexfer.core.bean.RemoteFile; 8 | import top.weixiansen574.hybridfilexfer.droidcore.HFXServer; 9 | 10 | public class SendFilesToRemoteTask extends BackstageTask { 11 | private final HFXServer server; 12 | private final List files; 13 | private final Directory localDir; 14 | private final Directory remoteDir; 15 | public SendFilesToRemoteTask(BTransferFileCallback uiHandler, HFXServer server, List files, Directory localDir, Directory remoteDir) { 16 | super(uiHandler); 17 | this.server = server; 18 | this.files = files; 19 | this.localDir = localDir; 20 | this.remoteDir = remoteDir; 21 | } 22 | 23 | @Override 24 | protected void onStart(BTransferFileCallback callback) throws Throwable { 25 | server.sendFilesToRemote(files,localDir,remoteDir,callback); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/java/top/weixiansen574/hybridfilexfer/tasks/SendFilesToShelfTask.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.tasks; 2 | 3 | import java.util.List; 4 | 5 | import top.weixiansen574.async.BackstageTask; 6 | import top.weixiansen574.hybridfilexfer.core.bean.Directory; 7 | import top.weixiansen574.hybridfilexfer.core.bean.RemoteFile; 8 | import top.weixiansen574.hybridfilexfer.droidcore.HFXServer; 9 | 10 | public class SendFilesToShelfTask extends BackstageTask { 11 | private final HFXServer server; 12 | private final List files; 13 | private final Directory localDir; 14 | private final Directory remoteDir; 15 | public SendFilesToShelfTask(BTransferFileCallback uiHandler, HFXServer server, List files, Directory localDir, Directory remoteDir) { 16 | super(uiHandler); 17 | this.server = server; 18 | this.files = files; 19 | this.localDir = localDir; 20 | this.remoteDir = remoteDir; 21 | } 22 | 23 | @Override 24 | protected void onStart(BTransferFileCallback callback) throws Throwable { 25 | server.sendFilesToShelf(files,localDir,remoteDir,callback); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/anim/list_anim.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/baseline_add_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/baseline_arrow_outward_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/baseline_bookmark_add_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/baseline_bookmarks_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/baseline_check_circle_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/baseline_delete_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/baseline_file_download_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/baseline_grid_view_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/baseline_more_vert_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/baseline_phonelink_ring_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/baseline_refresh_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/baseline_select_all_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/baseline_speed_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/baseline_update_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/baseline_upload_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/bt.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/ethernet.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/file.xml: -------------------------------------------------------------------------------- 1 | 6 | 11 | 14 | 17 | 20 | 21 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/folder.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 15 | 18 | 21 | 22 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/github.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/ic_close.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-Android/app/src/main/res/drawable/logo.png -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/shadow_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/shadow_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/shadow_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/shadow_top.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/usb.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/drawable/wifi.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/layout/activity_client.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 19 | 20 | 29 | 30 | 31 | 36 | 37 | 43 | 44 | 54 | 55 | 66 | 67 | 68 | 79 | 80 | 81 | 82 | 83 | 88 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/layout/dialog_bookmarks.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/layout/dialog_buffer_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 21 | 22 | 32 | 33 | 40 | 41 | 51 | 52 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/layout/dialog_connect_server.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 12 | 23 | 24 | 30 | 31 | 32 | 33 | 41 | 42 | 53 | 54 | 62 | 63 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/layout/dialog_transfer.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/layout/edit_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 15 | 16 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/layout/item_bookmark.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 25 | 26 | 27 | 28 | 29 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/layout/item_file.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 25 | 26 | 27 | 28 | 42 | 43 | 52 | 53 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/layout/item_net_card_info.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 22 | 23 | 34 | 35 | 43 | 44 | 53 | 54 | 55 | 61 | 62 | 69 | 70 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/layout/item_net_interface_status.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 16 | 17 | 22 | 23 | 33 | 34 | 44 | 45 | 46 | 56 | 98 | 99 | 100 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/layout/toolbar_select.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/menu/main_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 10 | 14 | 18 | 22 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/menu/select_toolbar_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 10 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/menu/toolbar_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 10 | 14 | 18 | 22 | 26 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | @color/white 4 | #8AB4F8 5 | #394456 6 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/values/arrays.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | @string/normal 5 | Root 6 | ADB 7 | 8 | 9 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FF000000 4 | #FFFFFFFF 5 | #212121 6 | #1E88E5 7 | #E3F2FD 8 | @color/black 9 | #59000000 10 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 15 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/app/src/test/java/top/weixiansen574/hybridfilexfer2/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer2; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /HybridFileXfer-Android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | plugins { 3 | id 'com.android.application' version '8.1.3' apply false 4 | } -------------------------------------------------------------------------------- /HybridFileXfer-Android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Enables namespacing of each library's R class so that its R class includes only the 19 | # resources declared in the library itself and none from the library's dependencies, 20 | # thereby reducing the size of the R class for that library 21 | android.nonTransitiveRClass=true 22 | android.enableResourceOptimizations=false -------------------------------------------------------------------------------- /HybridFileXfer-Android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-Android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /HybridFileXfer-Android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Sep 21 16:38:51 CST 2024 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /HybridFileXfer-Android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | gradlePluginPortal() 6 | maven { url 'https://jitpack.io' } 7 | } 8 | } 9 | dependencyResolutionManagement { 10 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 11 | repositories { 12 | google() 13 | mavenCentral() 14 | maven { url 'https://jitpack.io' } 15 | } 16 | } 17 | 18 | rootProject.name = "HybridFileXfer" 19 | include ':app' 20 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # 默认忽略的文件 2 | /shelf/ 3 | /workspace.xml 4 | # 基于编辑器的 HTTP 客户端请求 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/.idea/HybridFileXfer-PC.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/.idea/artifacts/HybridFileXfer_PC_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | $PROJECT_DIR$/out/artifacts/HybridFileXfer_PC_jar 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/AdbWinApi.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/AdbWinApi.dll -------------------------------------------------------------------------------- /HybridFileXfer-PC/AdbWinUsbApi.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/AdbWinUsbApi.dll -------------------------------------------------------------------------------- /HybridFileXfer-PC/HybridFileXfer-PC.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/adb.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/adb.exe -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/artifacts/HybridFileXfer_PC_jar/HybridFileXfer-PC.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/artifacts/HybridFileXfer_PC_jar/HybridFileXfer-PC.jar -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: top.weixiansen574.hybridfilexfer.Main 3 | 4 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/messages_en.properties: -------------------------------------------------------------------------------- 1 | usage=Control channel connection method not specified\nParameter description:\n-c Connection method: \"adb\" or network IP\n-s Specify the device for adb mode (when multiple devices are connected via adb). You can use the \"adb devices\" command to check the device list.\nExample:\n-c adb\n-c adb -s abcd1234\n-c 192.168.1.2 2 | adb_forward_succeed=USB_ADB: Port 5740 forwarding successful! 3 | connecting_control_channel=Connecting to control channel: %s 4 | version_mismatch=Protocol version mismatch. Your version: %d, Remote version: %d 5 | connect_control_failed=Failed to connect to the control channel. Please check if the mobile server is running. 6 | connecting_transfer_channel=Connecting... Network Interface: %s, Remote Address: %s, Bind Address: %s 7 | connect_transfer_failed=Transfer channel connection failed! Interface: %s, Address: %s, Error: %s 8 | out_of_memory=Out of memory! Failed to create buffer blocks. Created: %d, Required: %d. Max available memory: %dMB 9 | java_32bit_warning=Detected 32-bit Java. Memory is limited. Consider using 64-bit Java. 10 | remote_out_of_memory=Connection failed. Insufficient memory on the mobile side. Please follow the mobile device instructions. 11 | connect_success=Connection complete. 12 | receiving_files=Receiving files... 13 | sending_files=Sending files... 14 | client_exit=Received stop command. Client has shut down successfully. 15 | channel_complete=%s transfer complete! Average speed: %s 16 | channel_error_exception=Exception occurred during %s transfer: %s 17 | channel_error_interrupt=%s transfer interrupted due to an error in another channel. 18 | channel_error_read=Read error while transferring %s 19 | channel_error_write=Write error while transferring %s 20 | file_read_error=Error reading file: %s 21 | file_write_error=Error writing file: %s 22 | upload_complete=File upload complete. Avg speed: %s, Time: %s, Data transferred: %s 23 | download_complete=File download complete. Avg speed: %s, Time: %s, Data transferred: %s 24 | transfer_failed=Transfer failed. 25 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/messages_ja.properties: -------------------------------------------------------------------------------- 1 | usage=制御チャンネルの接続方法が指定されていません\nパラメータの説明:\n-c 制御チャンネルの接続方法 \"adb\" または ネットワークIP\n-s adbモードで指定するデバイス(adbに複数のデバイスが接続されている場合)。\"adb devices\" コマンドでデバイスを確認できます。\n例:\n-c adb\n-c adb -s abcd1234\n-c 192.168.1.2 2 | adb_forward_succeed=USB_ADB: ポート 5740 の転送が成功しました! 3 | connecting_control_channel=制御チャンネルに接続中:%s 4 | version_mismatch=プロトコルバージョンの不一致。あなたのバージョン:%d、相手のバージョン:%d 5 | connect_control_failed=制御チャンネルへの接続に失敗しました。モバイルサーバーが起動しているか確認してください。 6 | connecting_transfer_channel=接続中... ネットワークインターフェース:%s、リモートアドレス:%s、バインドアドレス:%s 7 | connect_transfer_failed=転送チャンネルの接続に失敗しました! インターフェース:%s、アドレス:%s、エラー:%s 8 | out_of_memory=メモリ不足! バッファブロックの作成に失敗しました。作成済み:%d、必要数:%d。最大利用可能メモリ:%dMB 9 | java_32bit_warning=32ビットJavaが検出されました。メモリ制限があります。64ビットJavaの使用を推奨します。 10 | remote_out_of_memory=接続失敗。モバイル側のメモリ不足です。指示に従ってください。 11 | connect_success=接続完了。 12 | receiving_files=ファイルを受信中… 13 | sending_files=ファイルを送信中… 14 | client_exit=終了指示を受けました。クライアントが正常に終了しました。 15 | channel_complete=%s 転送完了! 平均速度:%s 16 | channel_error_exception=%s の転送中にエラーが発生しました:%s 17 | channel_error_interrupt=他のチャンネルのエラーにより %s の転送が中断されました。 18 | channel_error_read=%s の読み取りエラーが発生しました。 19 | channel_error_write=%s の書き込みエラーが発生しました。 20 | file_read_error=ファイルの読み取り中にエラーが発生しました:%s 21 | file_write_error=ファイルの書き込み中にエラーが発生しました:%s 22 | upload_complete=ファイルアップロード完了。平均速度:%s、時間:%s、転送量:%s 23 | download_complete=ファイルダウンロード完了。平均速度:%s、時間:%s、転送量:%s 24 | transfer_failed=転送に失敗しました。 25 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/messages_ko.properties: -------------------------------------------------------------------------------- 1 | usage=제어 채널 연결 방법이 지정되지 않았습니다\n매개변수 설명:\n-c 제어 채널 연결 방식 \"adb\" 또는 네트워크 IP\n-s adb 모드에서 특정 장치를 지정 (adb에 여러 장치가 연결된 경우). \"adb devices\" 명령어로 장치를 확인할 수 있습니다.\n예시:\n-c adb\n-c adb -s abcd1234\n-c 192.168.1.2 2 | adb_forward_succeed=USB_ADB: 포트 5740 포워딩 성공! 3 | connecting_control_channel=제어 채널에 연결 중: %s 4 | version_mismatch=프로토콜 버전 불일치. 내 버전: %d, 상대 버전: %d 5 | connect_control_failed=제어 채널 연결 실패. 모바일 서버가 실행 중인지 확인하세요. 6 | connecting_transfer_channel=연결 중... 네트워크 인터페이스: %s, 원격 주소: %s, 바인드 주소: %s 7 | connect_transfer_failed=전송 채널 연결 실패! 인터페이스: %s, 주소: %s, 오류: %s 8 | out_of_memory=메모리 부족! 버퍼 블록 생성 실패. 생성된 블록: %d, 필요 블록: %d. 최대 사용 가능 메모리: %dMB 9 | java_32bit_warning=32비트 Java 감지됨. 메모리 제한이 있습니다. 64비트 Java 사용을 권장합니다. 10 | remote_out_of_memory=연결 실패. 모바일 장치의 메모리가 부족합니다. 안내를 따르세요. 11 | connect_success=연결 완료. 12 | receiving_files=파일 수신 중... 13 | sending_files=파일 전송 중... 14 | client_exit=종료 명령을 받았습니다. 클라이언트가 정상적으로 종료되었습니다. 15 | channel_complete=%s 전송 완료! 평균 속도: %s 16 | channel_error_exception=%s 전송 중 오류 발생: %s 17 | channel_error_interrupt=다른 채널 오류로 인해 %s 전송이 중단되었습니다. 18 | channel_error_read=%s 읽기 오류 발생. 19 | channel_error_write=%s 쓰기 오류 발생. 20 | file_read_error=파일 읽기 오류: %s 21 | file_write_error=파일 쓰기 오류: %s 22 | upload_complete=파일 업로드 완료. 평균 속도: %s, 시간: %s, 전송량: %s 23 | download_complete=파일 다운로드 완료. 평균 속도: %s, 시간: %s, 전송량: %s 24 | transfer_failed=전송 실패. 25 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/messages_zh_CN.properties: -------------------------------------------------------------------------------- 1 | usage=未指定控制通道连接方式\n参数说明:\n-c 控制通道连接方式 \"adb\" 或 网络ip\n-s adb连接方式下指定的设备(adb有多设备的情况),你可以用\"adb devices\"命令查看设备\n示例:\n-c adb\n-c adb -s abcd1234\n-c 192.168.1.2 2 | adb_forward_succeed=USB_ADB : 5740 端口转发成功! 3 | connecting_control_channel=正在连接控制通道:%s 4 | version_mismatch=协议版本不一致,你的版本:%d,对方版本:%d 5 | connect_control_failed=控制通道连接到手机失败,请检查手机的服务端是否启动? 6 | connecting_transfer_channel=正在连接 网卡名:%s 远程地址:%s 绑定地址:%s 7 | connect_transfer_failed=传输通道连接失败!网卡名:%s 地址:%s 异常信息:%s 8 | out_of_memory=内存不足,创建缓冲区块失败!成功创建%d块,需要%d块。当前最大可用内存:%dMB 9 | java_32bit_warning=检测你正在使用32位Java,内存受限,建议使用64位Java 10 | remote_out_of_memory=连接失败,手机端内存不足,请按照手机端的提示操作 11 | connect_success=连接完毕 12 | receiving_files=正在接收文件…… 13 | sending_files=正在发送文件…… 14 | client_exit=收到停止指令,客户端已正常关闭! 15 | channel_complete=%s 传输完毕!平均速度:%s 16 | channel_error_exception=%s 传输时发生异常:%s 17 | channel_error_interrupt=%s 因其他通道发生了错误,传输已中断 18 | channel_error_read=%s 读取文件时出错 19 | channel_error_write=%s 写入文件时出错 20 | file_read_error=读取文件时发生错误:%s 21 | file_write_error=写入文件时发生错误:%s 22 | upload_complete=文件发送完毕 平均速度:%s 耗时:%s 传输量:%s 23 | download_complete=文件接收完毕 平均速度:%s 耗时:%s 传输量:%s 24 | transfer_failed=传输失败 25 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/messages_zh_TW.properties: -------------------------------------------------------------------------------- 1 | usage=未指定控制通道連接方式\n參數說明:\n-c 控制通道連接方式 \"adb\" 或 網路IP\n-s adb連接方式下指定的設備(當adb有多個設備時),你可以用 \"adb devices\" 指令查看設備\n示例:\n-c adb\n-c adb -s abcd1234\n-c 192.168.1.2 2 | adb_forward_succeed=USB_ADB : 5740 端口轉發成功! 3 | connecting_control_channel=正在連接控制通道:%s 4 | version_mismatch=協議版本不一致,你的版本:%d,對方版本:%d 5 | connect_control_failed=控制通道連接到手機失敗,請檢查手機的服務端是否啟動? 6 | connecting_transfer_channel=正在連接 網卡名:%s 遠程地址:%s 綁定地址:%s 7 | connect_transfer_failed=傳輸通道連接失敗!網卡名:%s 地址:%s 異常信息:%s 8 | out_of_memory=記憶體不足,創建緩衝區塊失敗!成功創建%d塊,需要%d塊。當前最大可用記憶體:%dMB 9 | java_32bit_warning=偵測到您正在使用32位Java,記憶體受限,建議使用64位Java 10 | remote_out_of_memory=連接失敗,手機端記憶體不足,請按照手機端的提示操作 11 | connect_success=連接完畢 12 | receiving_files=正在接收檔案…… 13 | sending_files=正在發送檔案…… 14 | client_exit=收到停止指令,客戶端已正常關閉! 15 | channel_complete=%s 傳輸完畢!平均速度:%s 16 | channel_error_exception=%s 傳輸時發生異常:%s 17 | channel_error_interrupt=%s 因其他通道發生錯誤,傳輸已中斷 18 | channel_error_read=%s 讀取檔案時出錯 19 | channel_error_write=%s 寫入檔案時出錯 20 | file_read_error=讀取檔案時發生錯誤:%s 21 | file_write_error=寫入檔案時發生錯誤:%s 22 | upload_complete=檔案傳送完畢 平均速度:%s 耗時:%s 傳輸量:%s 23 | download_complete=檔案接收完畢 平均速度:%s 耗時:%s 傳輸量:%s 24 | transfer_failed=傳輸失敗 25 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/Main$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/Main$1.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/Main$2.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/Main$2.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/Main.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/Main.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/Strings$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/Strings$1.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/Strings.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/Strings.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/ControllerIdentifiers.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/ControllerIdentifiers.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/FileBlock.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/FileBlock.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/HFXClient.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/HFXClient.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/HFXService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/HFXService.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/ReadFileCall.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/ReadFileCall.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/ReceiveFileCall.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/ReceiveFileCall.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/SendFileCall.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/SendFileCall.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/SpeedMonitorThread.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/SpeedMonitorThread.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/TransferConnection.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/TransferConnection.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/TransferIdentifiers.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/TransferIdentifiers.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/Utils.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/Utils.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/WriteFileCall.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/WriteFileCall.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/bean/Directory.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/bean/Directory.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/bean/RemoteFile.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/bean/RemoteFile.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/bean/ServerNetInterface.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/bean/ServerNetInterface.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/bean/TrafficInfo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/bean/TrafficInfo.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/callback/ClientCallBack.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/callback/ClientCallBack.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/callback/ConnectServerCallback.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/callback/ConnectServerCallback.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/callback/TransferFileCallback.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/core/callback/TransferFileCallback.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/jdkcore/JdkHFXClient.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/jdkcore/JdkHFXClient.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/jdkcore/JdkReadFileCall.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/jdkcore/JdkReadFileCall.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/jdkcore/JdkWriteFileCall.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/hybridfilexfer/jdkcore/JdkWriteFileCall.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/nio/DataByteChannel.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/out/production/HybridFileXfer-PC/top/weixiansen574/nio/DataByteChannel.class -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: top.weixiansen574.hybridfilexfer.Main 3 | 4 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/messages_en.properties: -------------------------------------------------------------------------------- 1 | usage=Control channel connection method not specified\nParameter description:\n-c Connection method: \"adb\" or network IP\n-s Specify the device for adb mode (when multiple devices are connected via adb). You can use the \"adb devices\" command to check the device list.\nExample:\n-c adb\n-c adb -s abcd1234\n-c 192.168.1.2 2 | adb_forward_succeed=USB_ADB: Port 5740 forwarding successful! 3 | connecting_control_channel=Connecting to control channel: %s 4 | version_mismatch=Protocol version mismatch. Your version: %d, Remote version: %d 5 | connect_control_failed=Failed to connect to the control channel. Please check if the mobile server is running. 6 | connecting_transfer_channel=Connecting... Network Interface: %s, Remote Address: %s, Bind Address: %s 7 | connect_transfer_failed=Transfer channel connection failed! Interface: %s, Address: %s, Error: %s 8 | out_of_memory=Out of memory! Failed to create buffer blocks. Created: %d, Required: %d. Max available memory: %dMB 9 | java_32bit_warning=Detected 32-bit Java. Memory is limited. Consider using 64-bit Java. 10 | remote_out_of_memory=Connection failed. Insufficient memory on the mobile side. Please follow the mobile device instructions. 11 | connect_success=Connection complete. 12 | receiving_files=Receiving files... 13 | sending_files=Sending files... 14 | client_exit=Received stop command. Client has shut down successfully. 15 | channel_complete=%s transfer complete! Average speed: %s 16 | channel_error_exception=Exception occurred during %s transfer: %s 17 | channel_error_interrupt=%s transfer interrupted due to an error in another channel. 18 | channel_error_read=Read error while transferring %s 19 | channel_error_write=Write error while transferring %s 20 | file_read_error=Error reading file: %s 21 | file_write_error=Error writing file: %s 22 | upload_complete=File upload complete. Avg speed: %s, Time: %s, Data transferred: %s 23 | download_complete=File download complete. Avg speed: %s, Time: %s, Data transferred: %s 24 | transfer_failed=Transfer failed. 25 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/messages_ja.properties: -------------------------------------------------------------------------------- 1 | usage=制御チャンネルの接続方法が指定されていません\nパラメータの説明:\n-c 制御チャンネルの接続方法 \"adb\" または ネットワークIP\n-s adbモードで指定するデバイス(adbに複数のデバイスが接続されている場合)。\"adb devices\" コマンドでデバイスを確認できます。\n例:\n-c adb\n-c adb -s abcd1234\n-c 192.168.1.2 2 | adb_forward_succeed=USB_ADB: ポート 5740 の転送が成功しました! 3 | connecting_control_channel=制御チャンネルに接続中:%s 4 | version_mismatch=プロトコルバージョンの不一致。あなたのバージョン:%d、相手のバージョン:%d 5 | connect_control_failed=制御チャンネルへの接続に失敗しました。モバイルサーバーが起動しているか確認してください。 6 | connecting_transfer_channel=接続中... ネットワークインターフェース:%s、リモートアドレス:%s、バインドアドレス:%s 7 | connect_transfer_failed=転送チャンネルの接続に失敗しました! インターフェース:%s、アドレス:%s、エラー:%s 8 | out_of_memory=メモリ不足! バッファブロックの作成に失敗しました。作成済み:%d、必要数:%d。最大利用可能メモリ:%dMB 9 | java_32bit_warning=32ビットJavaが検出されました。メモリ制限があります。64ビットJavaの使用を推奨します。 10 | remote_out_of_memory=接続失敗。モバイル側のメモリ不足です。指示に従ってください。 11 | connect_success=接続完了。 12 | receiving_files=ファイルを受信中… 13 | sending_files=ファイルを送信中… 14 | client_exit=終了指示を受けました。クライアントが正常に終了しました。 15 | channel_complete=%s 転送完了! 平均速度:%s 16 | channel_error_exception=%s の転送中にエラーが発生しました:%s 17 | channel_error_interrupt=他のチャンネルのエラーにより %s の転送が中断されました。 18 | channel_error_read=%s の読み取りエラーが発生しました。 19 | channel_error_write=%s の書き込みエラーが発生しました。 20 | file_read_error=ファイルの読み取り中にエラーが発生しました:%s 21 | file_write_error=ファイルの書き込み中にエラーが発生しました:%s 22 | upload_complete=ファイルアップロード完了。平均速度:%s、時間:%s、転送量:%s 23 | download_complete=ファイルダウンロード完了。平均速度:%s、時間:%s、転送量:%s 24 | transfer_failed=転送に失敗しました。 25 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/messages_ko.properties: -------------------------------------------------------------------------------- 1 | usage=제어 채널 연결 방법이 지정되지 않았습니다\n매개변수 설명:\n-c 제어 채널 연결 방식 \"adb\" 또는 네트워크 IP\n-s adb 모드에서 특정 장치를 지정 (adb에 여러 장치가 연결된 경우). \"adb devices\" 명령어로 장치를 확인할 수 있습니다.\n예시:\n-c adb\n-c adb -s abcd1234\n-c 192.168.1.2 2 | adb_forward_succeed=USB_ADB: 포트 5740 포워딩 성공! 3 | connecting_control_channel=제어 채널에 연결 중: %s 4 | version_mismatch=프로토콜 버전 불일치. 내 버전: %d, 상대 버전: %d 5 | connect_control_failed=제어 채널 연결 실패. 모바일 서버가 실행 중인지 확인하세요. 6 | connecting_transfer_channel=연결 중... 네트워크 인터페이스: %s, 원격 주소: %s, 바인드 주소: %s 7 | connect_transfer_failed=전송 채널 연결 실패! 인터페이스: %s, 주소: %s, 오류: %s 8 | out_of_memory=메모리 부족! 버퍼 블록 생성 실패. 생성된 블록: %d, 필요 블록: %d. 최대 사용 가능 메모리: %dMB 9 | java_32bit_warning=32비트 Java 감지됨. 메모리 제한이 있습니다. 64비트 Java 사용을 권장합니다. 10 | remote_out_of_memory=연결 실패. 모바일 장치의 메모리가 부족합니다. 안내를 따르세요. 11 | connect_success=연결 완료. 12 | receiving_files=파일 수신 중... 13 | sending_files=파일 전송 중... 14 | client_exit=종료 명령을 받았습니다. 클라이언트가 정상적으로 종료되었습니다. 15 | channel_complete=%s 전송 완료! 평균 속도: %s 16 | channel_error_exception=%s 전송 중 오류 발생: %s 17 | channel_error_interrupt=다른 채널 오류로 인해 %s 전송이 중단되었습니다. 18 | channel_error_read=%s 읽기 오류 발생. 19 | channel_error_write=%s 쓰기 오류 발생. 20 | file_read_error=파일 읽기 오류: %s 21 | file_write_error=파일 쓰기 오류: %s 22 | upload_complete=파일 업로드 완료. 평균 속도: %s, 시간: %s, 전송량: %s 23 | download_complete=파일 다운로드 완료. 평균 속도: %s, 시간: %s, 전송량: %s 24 | transfer_failed=전송 실패. 25 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/messages_zh_CN.properties: -------------------------------------------------------------------------------- 1 | usage=未指定控制通道连接方式\n参数说明:\n-c 控制通道连接方式 \"adb\" 或 网络ip\n-s adb连接方式下指定的设备(adb有多设备的情况),你可以用\"adb devices\"命令查看设备\n示例:\n-c adb\n-c adb -s abcd1234\n-c 192.168.1.2 2 | adb_forward_succeed=USB_ADB : 5740 端口转发成功! 3 | connecting_control_channel=正在连接控制通道:%s 4 | version_mismatch=协议版本不一致,你的版本:%d,对方版本:%d 5 | connect_control_failed=控制通道连接到手机失败,请检查手机的服务端是否启动? 6 | connecting_transfer_channel=正在连接 网卡名:%s 远程地址:%s 绑定地址:%s 7 | connect_transfer_failed=传输通道连接失败!网卡名:%s 地址:%s 异常信息:%s 8 | out_of_memory=内存不足,创建缓冲区块失败!成功创建%d块,需要%d块。当前最大可用内存:%dMB 9 | java_32bit_warning=检测你正在使用32位Java,内存受限,建议使用64位Java 10 | remote_out_of_memory=连接失败,手机端内存不足,请按照手机端的提示操作 11 | connect_success=连接完毕 12 | receiving_files=正在接收文件…… 13 | sending_files=正在发送文件…… 14 | client_exit=收到停止指令,客户端已正常关闭! 15 | channel_complete=%s 传输完毕!平均速度:%s 16 | channel_error_exception=%s 传输时发生异常:%s 17 | channel_error_interrupt=%s 因其他通道发生了错误,传输已中断 18 | channel_error_read=%s 读取文件时出错 19 | channel_error_write=%s 写入文件时出错 20 | file_read_error=读取文件时发生错误:%s 21 | file_write_error=写入文件时发生错误:%s 22 | upload_complete=文件发送完毕 平均速度:%s 耗时:%s 传输量:%s 23 | download_complete=文件接收完毕 平均速度:%s 耗时:%s 传输量:%s 24 | transfer_failed=传输失败 25 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/messages_zh_TW.properties: -------------------------------------------------------------------------------- 1 | usage=未指定控制通道連接方式\n參數說明:\n-c 控制通道連接方式 \"adb\" 或 網路IP\n-s adb連接方式下指定的設備(當adb有多個設備時),你可以用 \"adb devices\" 指令查看設備\n示例:\n-c adb\n-c adb -s abcd1234\n-c 192.168.1.2 2 | adb_forward_succeed=USB_ADB : 5740 端口轉發成功! 3 | connecting_control_channel=正在連接控制通道:%s 4 | version_mismatch=協議版本不一致,你的版本:%d,對方版本:%d 5 | connect_control_failed=控制通道連接到手機失敗,請檢查手機的服務端是否啟動? 6 | connecting_transfer_channel=正在連接 網卡名:%s 遠程地址:%s 綁定地址:%s 7 | connect_transfer_failed=傳輸通道連接失敗!網卡名:%s 地址:%s 異常信息:%s 8 | out_of_memory=記憶體不足,創建緩衝區塊失敗!成功創建%d塊,需要%d塊。當前最大可用記憶體:%dMB 9 | java_32bit_warning=偵測到您正在使用32位Java,記憶體受限,建議使用64位Java 10 | remote_out_of_memory=連接失敗,手機端記憶體不足,請按照手機端的提示操作 11 | connect_success=連接完畢 12 | receiving_files=正在接收檔案…… 13 | sending_files=正在發送檔案…… 14 | client_exit=收到停止指令,客戶端已正常關閉! 15 | channel_complete=%s 傳輸完畢!平均速度:%s 16 | channel_error_exception=%s 傳輸時發生異常:%s 17 | channel_error_interrupt=%s 因其他通道發生錯誤,傳輸已中斷 18 | channel_error_read=%s 讀取檔案時出錯 19 | channel_error_write=%s 寫入檔案時出錯 20 | file_read_error=讀取檔案時發生錯誤:%s 21 | file_write_error=寫入檔案時發生錯誤:%s 22 | upload_complete=檔案傳送完畢 平均速度:%s 耗時:%s 傳輸量:%s 23 | download_complete=檔案接收完畢 平均速度:%s 耗時:%s 傳輸量:%s 24 | transfer_failed=傳輸失敗 25 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/top/weixiansen574/hybridfilexfer/Strings.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.InputStreamReader; 6 | import java.nio.charset.StandardCharsets; 7 | import java.util.*; 8 | 9 | public class Strings { 10 | 11 | private static final ResourceBundle messages; 12 | 13 | static { 14 | //由于Java读取properties文件用的是ISO-8859-1编码,这里加个Control让它用UTF-8编码来读 15 | messages = ResourceBundle.getBundle("messages", Locale.getDefault(), new ResourceBundle.Control() { 16 | @Override 17 | public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) 18 | throws IOException { 19 | String bundleName = toBundleName(baseName, locale); 20 | String resourceName = toResourceName(bundleName, "properties"); 21 | try (InputStream stream = loader.getResourceAsStream(resourceName)) { 22 | if (stream == null) { 23 | return null; 24 | } 25 | try (InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) { 26 | return new PropertyResourceBundle(reader); 27 | } 28 | } 29 | } 30 | }); 31 | } 32 | 33 | public static String get(String key) { 34 | return messages.getString(key); 35 | } 36 | 37 | public static String get(String key, Object... args) { 38 | String message = messages.getString(key); 39 | return String.format(message, args); // 使用占位符替换 40 | } 41 | 42 | public static void printf(String key){ 43 | System.out.println(get(key)); 44 | } 45 | 46 | public static void printf(String key, Object... args){ 47 | System.out.println(get(key, args)); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/top/weixiansen574/hybridfilexfer/core/ControllerIdentifiers.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core; 2 | 3 | public class ControllerIdentifiers { 4 | public static final short SHUTDOWN = 0; 5 | public static final short LIST_FILES = 1; 6 | public static final short DELETE_FILE = 2; 7 | public static final short MKDIR = 3; 8 | public static final short REQUEST_RECEIVE = 10; 9 | public static final short REQUEST_SEND = 11; 10 | 11 | //就让魔法打败魔法吧! 12 | /** 13 | * 禁止转载应用到酷安 14 | * 不许未经授权将本项目爬取到国内平台,点名GitCode,除非你的平台容得下下面的数字😁 15 | */ 16 | private static final int 酷安飞机杯 = 8964; 17 | /** 18 | * 你号没了! 19 | * 当然,如果你看到了有人在酷安分享本软件,请拿此内容进行举报攻击,让他狠狠的享受以下内容! 20 | * 你的账号【___】,存在发布涉政信息的违规行为,已禁止访问 21 | */ 22 | private static final String 威武小姐姐 = "学“习”通😋"; 23 | 24 | } -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/top/weixiansen574/hybridfilexfer/core/FileBlock.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core; 2 | 3 | import java.io.File; 4 | import java.nio.ByteBuffer; 5 | 6 | public class FileBlock implements Comparable { 7 | public static final int BLOCK_SIZE = 1024*1024;//1MB 8 | 9 | public final boolean isFile; 10 | public final int fileIndex; 11 | public final String path; 12 | public final long lastModified; 13 | public final long totalSize; 14 | public final int index; 15 | public final ByteBuffer data; 16 | 17 | public FileBlock(boolean isFile, int fileIndex, String path, long lastModified, long totalSize, int index, ByteBuffer data) { 18 | this.isFile = isFile; 19 | this.fileIndex = fileIndex; 20 | this.path = path; 21 | this.lastModified = lastModified; 22 | this.totalSize = totalSize; 23 | this.index = index; 24 | this.data = data; 25 | } 26 | 27 | public long getStartPosition(){ 28 | return BLOCK_SIZE * ((long) index); 29 | } 30 | 31 | public long calcBlockCount(){ 32 | return totalSize / BLOCK_SIZE + 1; 33 | } 34 | 35 | public boolean isFile(){ 36 | return isFile; 37 | } 38 | 39 | public boolean isDirectory(){ 40 | return !isFile; 41 | } 42 | 43 | public int getLength(){ 44 | if (data == null){ 45 | return -1; 46 | } 47 | return data.position(); 48 | } 49 | 50 | @Override 51 | public int compareTo(FileBlock other) { 52 | if (this.fileIndex != other.fileIndex) { 53 | return Integer.compare(this.fileIndex, other.fileIndex); 54 | } 55 | // 如果 nameIndex 相同,比较 index 56 | return Integer.compare(this.index, other.index); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/top/weixiansen574/hybridfilexfer/core/SendFileCall.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core; 2 | 3 | import java.util.concurrent.Callable; 4 | 5 | import top.weixiansen574.hybridfilexfer.core.callback.TransferFileCallback; 6 | import top.weixiansen574.nio.DataByteChannel; 7 | 8 | public class SendFileCall implements Callable { 9 | private final ReadFileCall readFileCall; 10 | private final DataByteChannel channel; 11 | private final TransferConnection connection; 12 | private final TransferFileCallback callback; 13 | 14 | public SendFileCall(ReadFileCall readFileCall, TransferConnection connection, TransferFileCallback callback) { 15 | this.readFileCall = readFileCall; 16 | this.connection = connection; 17 | this.channel = connection.channel; 18 | this.callback = callback; 19 | connection.resetTotalTrafficInfo(); 20 | } 21 | 22 | @Override 23 | public Void call() throws Exception { 24 | FileBlock fileBlock = null; 25 | try { 26 | long startTime = System.currentTimeMillis(); 27 | while (true) { 28 | fileBlock = readFileCall.takeBlock(); 29 | //-1为特殊块 30 | if (fileBlock.fileIndex == -1) { 31 | if (fileBlock == ReadFileCall.END_POINT) { 32 | channel.writeShort(TransferIdentifiers.EOF); 33 | callback.onChannelComplete(connection.iName, 34 | connection.getTotalTraffic().uploadTraffic, 35 | System.currentTimeMillis() - startTime); 36 | } else if (fileBlock == ReadFileCall.INTERRUPT) { 37 | channel.writeShort(TransferIdentifiers.END_OF_INTERRUPTED); 38 | callback.onChannelError(connection.iName,TransferFileCallback.ERROR_TYPE_INTERRUPT, null); 39 | } else if (fileBlock == ReadFileCall.READ_ERROR) { 40 | channel.writeShort(TransferIdentifiers.END_OF_READ_ERROR); 41 | callback.onChannelError(connection.iName,TransferFileCallback.ERROR_TYPE_READ_ERROR, null); 42 | } else if (fileBlock == ReadFileCall.WRITE_ERROR) { 43 | channel.writeShort(TransferIdentifiers.END_OF_WRITE_ERROR); 44 | callback.onChannelError(connection.iName,TransferFileCallback.ERROR_TYPE_WRITE_ERROR, null); 45 | } 46 | break; 47 | } 48 | channel.writeShort(fileBlock.isFile ? TransferIdentifiers.FILE : 49 | TransferIdentifiers.FOLDER);//是否文件夹 50 | channel.writeInt(fileBlock.fileIndex); 51 | channel.writeUTF(fileBlock.path);//路径 52 | channel.writeLong(fileBlock.lastModified);//修改日期 53 | if (!fileBlock.isFile) continue; 54 | channel.writeLong(fileBlock.totalSize);//总大小 55 | channel.writeInt(fileBlock.index);//索引 56 | channel.writeInt(fileBlock.getLength());//单块的长度 57 | 58 | callback.onFileUploading(connection.iName, fileBlock.path, 59 | fileBlock.getStartPosition() + fileBlock.getLength(), 60 | fileBlock.totalSize); 61 | 62 | fileBlock.data.flip(); 63 | channel.write(fileBlock.data); 64 | readFileCall.recycleBuffer(fileBlock.data); 65 | connection.addUploadedBytes(fileBlock.getLength()); 66 | } 67 | } catch (Exception e) { 68 | //若发生异常,通知其他传输通道,停止传输 69 | if (fileBlock != null){ 70 | //回收文件分块的ByteBuffer,否则导致这个Buffer免费了 71 | readFileCall.recycleBuffer(fileBlock.data); 72 | } 73 | readFileCall.shutdownByConnectionBreak(); 74 | callback.onChannelError(connection.iName,TransferFileCallback.ERROR_TYPE_EXCEPTION, e.toString()); 75 | throw e; 76 | } 77 | return null; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/top/weixiansen574/hybridfilexfer/core/SpeedMonitorThread.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import top.weixiansen574.hybridfilexfer.core.TransferConnection; 7 | import top.weixiansen574.hybridfilexfer.core.bean.TrafficInfo; 8 | import top.weixiansen574.hybridfilexfer.core.callback.TransferFileCallback; 9 | 10 | public class SpeedMonitorThread extends Thread { 11 | private boolean isRun = true; 12 | private final List connections; 13 | private final TransferFileCallback callback; 14 | 15 | public SpeedMonitorThread(List connections, TransferFileCallback callback) { 16 | this.connections = connections; 17 | this.callback = callback; 18 | } 19 | 20 | @Override 21 | @SuppressWarnings("BusyWait") 22 | public void run() { 23 | while (isRun){ 24 | try { 25 | Thread.sleep(1000); 26 | } catch (InterruptedException e) { 27 | break; 28 | } 29 | List trafficInfoList = new ArrayList<>(); 30 | for (TransferConnection channel : connections) { 31 | trafficInfoList.add(channel.resetCurrentTrafficInfo()); 32 | } 33 | callback.onSpeedInfo(trafficInfoList); 34 | } 35 | } 36 | 37 | public void cancel(){ 38 | isRun = false; 39 | interrupt(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/top/weixiansen574/hybridfilexfer/core/TransferConnection.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core; 2 | 3 | import java.io.IOException; 4 | 5 | import top.weixiansen574.hybridfilexfer.core.bean.TrafficInfo; 6 | import top.weixiansen574.nio.DataByteChannel; 7 | 8 | public class TransferConnection { 9 | public final String iName; 10 | private TrafficInfo currentTraffic; 11 | private TrafficInfo totalTraffic; 12 | public final DataByteChannel channel; 13 | 14 | public TransferConnection(String iName, DataByteChannel channel) throws IOException { 15 | this.iName = iName; 16 | this.channel = channel; 17 | currentTraffic = new TrafficInfo(); 18 | totalTraffic = new TrafficInfo(); 19 | } 20 | 21 | public synchronized void addUploadedBytes(long byteCount) { 22 | currentTraffic.uploadTraffic += byteCount; 23 | totalTraffic.uploadTraffic += byteCount; 24 | } 25 | 26 | public synchronized void addDownloadedBytes(long byteCount) { 27 | currentTraffic.downloadTraffic += byteCount; 28 | totalTraffic.downloadTraffic += byteCount; 29 | } 30 | 31 | public synchronized TrafficInfo resetCurrentTrafficInfo() { 32 | TrafficInfo info = currentTraffic; 33 | currentTraffic = new TrafficInfo(iName); 34 | return info; 35 | } 36 | 37 | public synchronized TrafficInfo resetTotalTrafficInfo() { 38 | TrafficInfo info = totalTraffic; 39 | totalTraffic = new TrafficInfo(iName); 40 | return info; 41 | } 42 | 43 | public synchronized TrafficInfo getTotalTraffic(){ 44 | return totalTraffic; 45 | } 46 | 47 | public void close() throws IOException { 48 | channel.close(); 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/top/weixiansen574/hybridfilexfer/core/TransferIdentifiers.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core; 2 | 3 | public class TransferIdentifiers { 4 | public static final short END_POINT = -1; 5 | public static final short FILE = 0; 6 | public static final short FOLDER = 1; 7 | public static final short FILE_SLICE = 2; 8 | public static final short EOF = 3; 9 | public static final short END_OF_INTERRUPTED = 4; 10 | public static final short END_OF_READ_ERROR = 5; 11 | public static final short END_OF_WRITE_ERROR = 6; 12 | } 13 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/top/weixiansen574/hybridfilexfer/core/Utils.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core; 2 | 3 | import java.io.File; 4 | import java.text.SimpleDateFormat; 5 | import java.util.ArrayList; 6 | import java.util.Date; 7 | import java.util.List; 8 | import java.util.Locale; 9 | 10 | import top.weixiansen574.hybridfilexfer.core.bean.RemoteFile; 11 | 12 | public class Utils { 13 | public static final String ILLEGAL_CHARACTERS = "<>:\"/\\|?*"; 14 | 15 | public static void sortFiles(List fileList) { 16 | // 使用Comparator自定义比较规则 17 | fileList.sort((f1, f2) -> { 18 | // 文件夹优先于文件 19 | if (f1.isDirectory() && !f2.isDirectory()) { 20 | return -1; 21 | } else if (!f1.isDirectory() && f2.isDirectory()) { 22 | return 1; 23 | } else { 24 | // 如果类型相同,则按名称排序 25 | return f1.getName().compareTo(f2.getName()); 26 | } 27 | }); 28 | } 29 | 30 | public static String formatSpeed(long bytesPerSecond) { 31 | if (bytesPerSecond < 1024) { 32 | return bytesPerSecond + "B/s"; 33 | } 34 | if (bytesPerSecond < 1024 * 1024) { 35 | return String.format(Locale.getDefault(), "%.2fKB/s", bytesPerSecond / 1024.0); 36 | } 37 | return String.format(Locale.getDefault(), "%.2fMB/s", bytesPerSecond / (1024.0 * 1024.0)); 38 | } 39 | 40 | public static String formatDateTime(long milliseconds) { 41 | //格式化为年-月-日 时:分 42 | return new SimpleDateFormat("yy-MM-dd HH:mm", Locale.getDefault()).format(new Date(milliseconds)); 43 | } 44 | 45 | /** 46 | * 格式化毫秒数为指定的时间格式。 47 | * 48 | * @param milliseconds 输入的毫秒数 49 | * @return 格式化后的时间字符串 50 | */ 51 | public static String formatTime(long milliseconds) { 52 | if (milliseconds < 0) { 53 | throw new IllegalArgumentException("毫秒数不能为负数"); 54 | } 55 | 56 | if (milliseconds < 1000) { 57 | return milliseconds + "ms"; 58 | } 59 | 60 | long totalSeconds = milliseconds / 1000; 61 | long hours = totalSeconds / 3600; 62 | long minutes = (totalSeconds % 3600) / 60; 63 | long seconds = totalSeconds % 60; 64 | 65 | if (hours == 0) { 66 | return String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds); 67 | } else { 68 | return String.format(Locale.getDefault(), "%02d:%02d:%02d", hours, minutes, seconds); 69 | } 70 | } 71 | 72 | public static String formatFileSize(long size) { 73 | if (size < 1024) { 74 | return size + "B"; 75 | } 76 | if (size < 1024 * 1024) { 77 | return String.format(Locale.getDefault(), "%.2fKB", size / 1024.0); 78 | } 79 | if (size < 1024 * 1024 * 1024) { 80 | return String.format(Locale.getDefault(), "%.2fMB", size / (1024.0 * 1024.0)); 81 | } 82 | return String.format(Locale.getDefault(), "%.2fGB", size / (1024.0 * 1024.0 * 1024.0)); 83 | } 84 | 85 | public static boolean containsIllegalCharacters(String text) { 86 | for (char c : ILLEGAL_CHARACTERS.toCharArray()) { 87 | if (text.indexOf(c) >= 0) { 88 | return true; // 如果找到非法字符,返回 true 89 | } 90 | } 91 | return false; // 如果没有找到非法字符,返回 false 92 | } 93 | 94 | public static List listRemoteFiles(String path){ 95 | File[] files = new File(path).listFiles(); 96 | if (files == null) { 97 | return null; 98 | } 99 | ArrayList remoteFiles = new ArrayList<>(files.length); 100 | for (File file : files) { 101 | remoteFiles.add(new RemoteFile(file)); 102 | } 103 | return remoteFiles; 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/top/weixiansen574/hybridfilexfer/core/bean/RemoteFile.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core.bean; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | 5 | import java.io.File; 6 | 7 | public class RemoteFile { 8 | protected final String name; 9 | protected final String path; 10 | protected final long lastModified; 11 | protected final long size; 12 | protected final boolean isDirectory; 13 | //public final String name; 14 | //public final String path; 15 | //public final long lastModified; 16 | //public final long size; 17 | //public final boolean isDirectory; 18 | 19 | public RemoteFile(File file) { 20 | this.path = file.getPath(); 21 | this.isDirectory = file.isDirectory(); 22 | this.name = file.getName(); 23 | this.lastModified = file.lastModified(); 24 | this.size = file.length(); 25 | } 26 | 27 | public RemoteFile(String name, String path, long lastModified, long size, boolean isDirectory){ 28 | this.name = name; 29 | this.path = path; 30 | this.lastModified = lastModified; 31 | this.size = size; 32 | this.isDirectory = isDirectory; 33 | } 34 | 35 | public RemoteFile(RemoteFile file){ 36 | this.name = file.name; 37 | this.path = file.path; 38 | this.lastModified = file.lastModified; 39 | this.size = file.size; 40 | this.isDirectory = file.isDirectory; 41 | } 42 | 43 | 44 | @NotNull 45 | @Override 46 | public String toString() { 47 | return "RemoteFile{" + 48 | "path='" + path + '\'' + 49 | ", isDirectory=" + isDirectory + 50 | '}'; 51 | } 52 | 53 | public String getPath() { 54 | return path; 55 | } 56 | 57 | public boolean isDirectory() { 58 | return isDirectory; 59 | } 60 | 61 | public String getName() { 62 | return name; 63 | } 64 | 65 | public long lastModified() { 66 | return lastModified; 67 | } 68 | 69 | public long getSize() { 70 | return size; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/top/weixiansen574/hybridfilexfer/core/bean/ServerNetInterface.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core.bean; 2 | 3 | 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.net.InetAddress; 7 | 8 | public class ServerNetInterface{ 9 | public final String name; 10 | public final InetAddress address; 11 | public final InetAddress clientBindAddress; 12 | 13 | public ServerNetInterface(String name, InetAddress address, InetAddress clientBindAddress) { 14 | this.name = name; 15 | this.address = address; 16 | this.clientBindAddress = clientBindAddress; 17 | } 18 | 19 | 20 | @NotNull 21 | @Override 22 | public String toString() { 23 | return "ServerNetInterface{" + 24 | "name='" + name + '\'' + 25 | ", address=" + address + 26 | ", clientBindAddress=" + clientBindAddress + 27 | '}'; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/top/weixiansen574/hybridfilexfer/core/bean/TrafficInfo.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core.bean; 2 | 3 | public class TrafficInfo { 4 | public String iName; 5 | public long uploadTraffic; 6 | public long downloadTraffic; 7 | 8 | public TrafficInfo(String iName, long uploadTraffic, long downloadTraffic) { 9 | this.iName = iName; 10 | this.uploadTraffic = uploadTraffic; 11 | this.downloadTraffic = downloadTraffic; 12 | } 13 | public TrafficInfo() { 14 | } 15 | public TrafficInfo(String iName) { 16 | this.iName = iName; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/top/weixiansen574/hybridfilexfer/core/callback/ClientCallBack.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core.callback; 2 | 3 | public interface ClientCallBack extends TransferFileCallback { 4 | void onReceiving(); 5 | void onSending(); 6 | void onExit(); 7 | } 8 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/top/weixiansen574/hybridfilexfer/core/callback/ConnectServerCallback.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core.callback; 2 | 3 | import java.net.InetAddress; 4 | import java.util.List; 5 | 6 | public interface ConnectServerCallback { 7 | void onConnectingControlChannel(String address, int port); 8 | 9 | void onVersionMismatch(int localVersion, int remoteVersion); 10 | 11 | void onConnectControlFailed(); 12 | 13 | void onConnectingTransferChannel( 14 | String name, 15 | InetAddress inetAddress, 16 | InetAddress bindAddress); 17 | 18 | void onConnectTransferChannelFailed(String name, InetAddress inetAddress, Exception e); 19 | 20 | void onOOM( 21 | int createdBuffers, 22 | int requiredBuffers, 23 | long maxMemoryMB, 24 | String osArch); 25 | 26 | void onRemoteOOM(); 27 | 28 | void onConnectSuccess(List channelNames); 29 | } 30 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/top/weixiansen574/hybridfilexfer/core/callback/TransferFileCallback.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.core.callback; 2 | 3 | import java.util.List; 4 | 5 | import top.weixiansen574.hybridfilexfer.core.bean.TrafficInfo; 6 | 7 | public interface TransferFileCallback { 8 | int ERROR_TYPE_EXCEPTION = 1; 9 | int ERROR_TYPE_INTERRUPT = 2; 10 | int ERROR_TYPE_READ_ERROR = 3; 11 | int ERROR_TYPE_WRITE_ERROR = 4; 12 | 13 | void onFileUploading(String iName, String path, long targetSize, long totalSize); 14 | 15 | void onFileDownloading(String iName, String path, long targetSize, long totalSize); 16 | 17 | void onSpeedInfo(List trafficInfoList); 18 | 19 | void onChannelComplete(String iName, long traffic, long time); 20 | 21 | void onChannelError(String iName, int errorType, String message);//异常信息 or 断开 22 | 23 | void onReadFileError(String message); 24 | 25 | void onWriteFileError(String message); 26 | 27 | void onComplete(boolean isUpload,long traffic, long time); 28 | 29 | //传输通道有其中一个断开时 30 | void onIncomplete(); 31 | 32 | } 33 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/top/weixiansen574/hybridfilexfer/jdkcore/JdkHFXClient.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.jdkcore; 2 | 3 | import top.weixiansen574.hybridfilexfer.core.HFXClient; 4 | import top.weixiansen574.hybridfilexfer.core.ReadFileCall; 5 | import top.weixiansen574.hybridfilexfer.core.Utils; 6 | import top.weixiansen574.hybridfilexfer.core.WriteFileCall; 7 | import top.weixiansen574.hybridfilexfer.core.bean.Directory; 8 | import top.weixiansen574.hybridfilexfer.core.bean.RemoteFile; 9 | 10 | import java.io.File; 11 | import java.nio.ByteBuffer; 12 | import java.util.List; 13 | import java.util.concurrent.LinkedBlockingDeque; 14 | 15 | public class JdkHFXClient extends HFXClient { 16 | 17 | public JdkHFXClient(String serverControllerAddress, int serverPort, String homeDir) { 18 | super(serverControllerAddress, serverPort, homeDir); 19 | } 20 | 21 | @Override 22 | public ByteBuffer createBuffer(int size) { 23 | return ByteBuffer.allocateDirect(size); 24 | } 25 | 26 | @Override 27 | public long getAvailableMemoryMB() { 28 | return Runtime.getRuntime().maxMemory() / (1024 * 1024); 29 | } 30 | 31 | @Override 32 | protected boolean deleteLocalFile(String path) throws Exception { 33 | File file = new File(path); 34 | if (!file.exists()) { 35 | System.out.println("文件或目录不存在: " + path); 36 | return false; 37 | } 38 | 39 | // 如果是目录,递归删除 40 | if (file.isDirectory()) { 41 | File[] files = file.listFiles(); 42 | if (files != null) { // 检查是否为空 43 | for (File subFile : files) { 44 | deleteLocalFile(subFile.getAbsolutePath()); 45 | } 46 | } 47 | } 48 | 49 | // 删除文件或空目录 50 | return file.delete(); 51 | } 52 | 53 | @Override 54 | protected boolean mkdir(String parent, String child) throws Exception { 55 | return new File(parent,child).mkdirs(); 56 | } 57 | 58 | @Override 59 | protected List listFiles(String path) throws Exception { 60 | return Utils.listRemoteFiles(path); 61 | } 62 | 63 | @Override 64 | protected WriteFileCall createWriteFileCall(LinkedBlockingDeque buffers, int dequeCount) { 65 | return new JdkWriteFileCall(buffers,dequeCount); 66 | } 67 | 68 | @Override 69 | protected ReadFileCall createReadFileCall(LinkedBlockingDeque buffers, List files, Directory localDir, Directory remoteDir, int operateThreadCount) { 70 | return new JdkReadFileCall(buffers,files,localDir,remoteDir,operateThreadCount); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/top/weixiansen574/hybridfilexfer/jdkcore/JdkReadFileCall.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.jdkcore; 2 | 3 | import top.weixiansen574.hybridfilexfer.core.ReadFileCall; 4 | import top.weixiansen574.hybridfilexfer.core.Utils; 5 | import top.weixiansen574.hybridfilexfer.core.bean.Directory; 6 | import top.weixiansen574.hybridfilexfer.core.bean.RemoteFile; 7 | 8 | import java.io.File; 9 | import java.io.RandomAccessFile; 10 | import java.nio.ByteBuffer; 11 | import java.nio.channels.FileChannel; 12 | import java.util.List; 13 | import java.util.concurrent.LinkedBlockingDeque; 14 | 15 | public class JdkReadFileCall extends ReadFileCall { 16 | private RandomAccessFile randomAccessFile; 17 | private FileChannel channel; 18 | 19 | public JdkReadFileCall(LinkedBlockingDeque buffers, List files, Directory localDir, Directory remoteDir, int operateThreadCount) { 20 | super(buffers, files, localDir, remoteDir, operateThreadCount); 21 | } 22 | 23 | @Override 24 | protected boolean fileExists(String path) throws Exception { 25 | return new File(path).exists(); 26 | } 27 | 28 | @Override 29 | protected List listFiles(String path) throws Exception { 30 | return Utils.listRemoteFiles(path); 31 | } 32 | 33 | @Override 34 | protected FileChannel openFile(String path) throws Exception { 35 | randomAccessFile = new RandomAccessFile(path, "r"); 36 | channel = randomAccessFile.getChannel(); 37 | return channel; 38 | } 39 | 40 | @Override 41 | protected void closeFile() throws Exception { 42 | channel.close(); 43 | randomAccessFile.close(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/src/top/weixiansen574/hybridfilexfer/jdkcore/JdkWriteFileCall.java: -------------------------------------------------------------------------------- 1 | package top.weixiansen574.hybridfilexfer.jdkcore; 2 | 3 | import top.weixiansen574.hybridfilexfer.core.WriteFileCall; 4 | 5 | import java.io.File; 6 | import java.io.IOException; 7 | import java.io.RandomAccessFile; 8 | import java.nio.ByteBuffer; 9 | import java.nio.channels.FileChannel; 10 | import java.util.concurrent.LinkedBlockingDeque; 11 | 12 | public class JdkWriteFileCall extends WriteFileCall { 13 | private RandomAccessFile file; 14 | private FileChannel channel; 15 | 16 | public JdkWriteFileCall(LinkedBlockingDeque buffers, int dequeCount) { 17 | super(buffers, dequeCount); 18 | } 19 | 20 | @Override 21 | protected void createParentDirIfNotExists(String path) throws Exception { 22 | File file = new File(path); 23 | File parentFile = file.getParentFile(); 24 | //如果就是根目录的情况 25 | if (parentFile == null) { 26 | return; 27 | } 28 | mkdirOrThrow(parentFile); 29 | } 30 | 31 | @Override 32 | protected void tryMkdirs(String path) throws Exception { 33 | mkdirOrThrow(new File(path)); 34 | } 35 | 36 | @Override 37 | protected FileChannel createAndOpenFile(String path, long length) throws Exception { 38 | file = new RandomAccessFile(path, "rw"); 39 | file.setLength(length); 40 | channel = file.getChannel(); 41 | return channel; 42 | } 43 | 44 | @Override 45 | protected void closeFile() throws Exception { 46 | channel.close(); 47 | file.close(); 48 | } 49 | 50 | @Override 51 | protected boolean setFileLastModified(String path, long time) throws Exception { 52 | return new File(path).setLastModified(time); 53 | } 54 | 55 | private void mkdirOrThrow(File file) throws IOException { 56 | if (file.exists()) { 57 | //如果存在且是一个文件则删除再创建成文件夹 58 | if (file.isFile()) { 59 | if (file.delete()) { 60 | if (!file.mkdirs()) { 61 | throw new IOException("cannot mkdirs " + file); 62 | } 63 | } else { 64 | throw new IOException("cannot delete file " + file); 65 | } 66 | } 67 | } else { 68 | if (!file.mkdirs()) { 69 | throw new IOException("cannot mkdirs " + file); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /HybridFileXfer-PC/start.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/HybridFileXfer-PC/start.exe -------------------------------------------------------------------------------- /IMG_20241125_235527.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/IMG_20241125_235527.jpg -------------------------------------------------------------------------------- /PixPin_2024-04-15_20-42-19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/PixPin_2024-04-15_20-42-19.png -------------------------------------------------------------------------------- /PixPin_2024-04-15_20-45-49.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/PixPin_2024-04-15_20-45-49.png -------------------------------------------------------------------------------- /Screenshot_2024-10-13-13-20-59-747_top.weixiansen574.hybridfilexfer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/Screenshot_2024-10-13-13-20-59-747_top.weixiansen574.hybridfilexfer.jpg -------------------------------------------------------------------------------- /Screenshot_2024-10-13-13-21-20-325_top.weixiansen574.hybridfilexfer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/Screenshot_2024-10-13-13-21-20-325_top.weixiansen574.hybridfilexfer.jpg -------------------------------------------------------------------------------- /Screenshot_2024-10-13-13-59-51-358_top.weixiansen574.hybridfilexfer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/Screenshot_2024-10-13-13-59-51-358_top.weixiansen574.hybridfilexfer.jpg -------------------------------------------------------------------------------- /Screenshot_2024-10-13-14-00-12-221_top.weixiansen574.hybridfilexfer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/Screenshot_2024-10-13-14-00-12-221_top.weixiansen574.hybridfilexfer.jpg -------------------------------------------------------------------------------- /Screenshot_2024-10-13-14-16-19-518_top.weixiansen574.hybridfilexfer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/Screenshot_2024-10-13-14-16-19-518_top.weixiansen574.hybridfilexfer.jpg -------------------------------------------------------------------------------- /Screenshot_2024-10-13-14-16-22-997_top.weixiansen574.hybridfilexfer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/Screenshot_2024-10-13-14-16-22-997_top.weixiansen574.hybridfilexfer.jpg -------------------------------------------------------------------------------- /Screenshot_2024-10-13-14-20-12-558_top.weixiansen574.hybridfilexfer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/Screenshot_2024-10-13-14-20-12-558_top.weixiansen574.hybridfilexfer.jpg -------------------------------------------------------------------------------- /script/USB-forward.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | chcp 65001 3 | setlocal enabledelayedexpansion 4 | 5 | :: Constants 6 | set PORT=5740 7 | 8 | :: Get the list of devices (skip the header line) 9 | set deviceCount=0 10 | for /f "skip=1 tokens=1" %%a in ('adb devices') do ( 11 | if not "%%a"=="" ( 12 | :: Exclude empty lines 13 | set /a deviceCount+=1 14 | set "device[!deviceCount!]=%%a" 15 | ) 16 | ) 17 | 18 | :: Check if exactly two devices are connected 19 | if %deviceCount% neq 2 ( 20 | echo Detected devices: %deviceCount%. Please connect exactly two phones! 21 | echo Connected devices: 22 | for /L %%i in (1,1,%deviceCount%) do ( 23 | call :printDeviceName !device[%%i]! 24 | ) 25 | pause 26 | exit /b 27 | ) 28 | 29 | :: Get the display names of the two devices (format: DeviceName:DeviceID) 30 | call :getDeviceDisplay 1 deviceDisplay1 31 | call :getDeviceDisplay 2 deviceDisplay2 32 | 33 | echo. 34 | echo Please select the device to be Phone A (server): 35 | echo 1. %deviceDisplay1% 36 | echo 2. %deviceDisplay2% 37 | set /p choice=Enter a number (1 or 2): 38 | 39 | if "%choice%"=="1" ( 40 | set "deviceA=%device[1]%" 41 | set "deviceB=%device[2]%" 42 | ) else if "%choice%"=="2" ( 43 | set "deviceA=%device[2]%" 44 | set "deviceB=%device[1]%" 45 | ) else ( 46 | echo Invalid selection, exiting. 47 | pause 48 | exit /b 49 | ) 50 | 51 | echo. 52 | echo Selected Phone A: %deviceA% 53 | echo Selected Phone B: %deviceB% 54 | 55 | echo. 56 | echo Setting up port forwarding... 57 | adb -s %deviceA% forward tcp:%PORT% tcp:%PORT% 58 | adb -s %deviceB% reverse tcp:%PORT% tcp:%PORT% 59 | 60 | echo. 61 | echo Port forwarding setup complete! 62 | pause 63 | exit /b 64 | 65 | :printDeviceName 66 | :: Parameter: Device ID, output format: DeviceName:DeviceID 67 | setlocal 68 | set "devID=%1" 69 | for /f "delims=" %%n in ('adb -s %devID% shell settings get global device_name 2^>nul') do ( 70 | set "devName=%%n" 71 | goto afterLoop2 72 | ) 73 | :afterLoop2 74 | if "%devName%"=="" set "devName=Unknown" 75 | echo %devName%:%devID% 76 | endlocal 77 | goto :eof 78 | 79 | :getDeviceDisplay 80 | :: Parameter 1: Device index; Parameter 2: Output variable name 81 | setlocal 82 | set "devID=" 83 | set "devID=!device[%1]!" 84 | for /f "delims=" %%n in ('adb -s !devID! shell settings get global device_name 2^>nul') do ( 85 | set "devName=%%n" 86 | goto afterLoop 87 | ) 88 | :afterLoop 89 | if "!devName!"=="" set "devName=Unknown" 90 | endlocal & set "%2=%devName%:!device[%1]!" 91 | goto :eof 92 | -------------------------------------------------------------------------------- /script/USB-forward.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PORT=5740 4 | 5 | # 获取设备列表(跳过标题行) 6 | devices=($(adb devices | awk 'NR>1 {print $1}' | grep -v "^$")) 7 | device_count=${#devices[@]} 8 | 9 | # 检查是否连接了两个设备 10 | if [ $device_count -ne 2 ]; then 11 | echo "Detected devices: $device_count. Please connect exactly two phones!" 12 | echo "Connected devices:" 13 | for dev_id in "${devices[@]}"; do 14 | dev_name=$(adb -s "$dev_id" shell 'settings get global device_name 2>/dev/null' | tr -d '\r') 15 | echo "${dev_name:-Unknown}:$dev_id" 16 | done 17 | read -n1 -p "Press any key to exit..." 18 | exit 1 19 | fi 20 | 21 | # 获取设备显示名称 22 | get_device_display() { 23 | local dev_id=$1 24 | local dev_name=$(adb -s "$dev_id" shell 'settings get global device_name 2>/dev/null' | tr -d '\r') 25 | echo "${dev_name:-Unknown}:$dev_id" 26 | } 27 | 28 | # 显示设备选择菜单 29 | echo 30 | echo "Please select the device to be Phone A (server):" 31 | echo "1. $(get_device_display "${devices[0]}")" 32 | echo "2. $(get_device_display "${devices[1]}")" 33 | read -n1 -p "Enter a number (1 or 2): " choice 34 | echo 35 | 36 | # 处理用户选择 37 | case $choice in 38 | 1) 39 | deviceA=${devices[0]} 40 | deviceB=${devices[1]} 41 | ;; 42 | 2) 43 | deviceA=${devices[1]} 44 | deviceB=${devices[0]} 45 | ;; 46 | *) 47 | echo "Invalid selection, exiting." 48 | read -n1 -p "Press any key to exit..." 49 | exit 1 50 | ;; 51 | esac 52 | 53 | echo 54 | echo "Selected Phone A: $deviceA" 55 | echo "Selected Phone B: $deviceB" 56 | 57 | # 设置端口转发 58 | echo 59 | echo "Setting up port forwarding..." 60 | adb -s "$deviceA" forward tcp:$PORT tcp:$PORT 61 | adb -s "$deviceB" reverse tcp:$PORT tcp:$PORT 62 | 63 | echo 64 | echo "Port forwarding setup complete!" 65 | read -n1 -p "Press any key to exit..." 66 | exit 0 -------------------------------------------------------------------------------- /script/USB-forward_中文.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | :: 避免其他繁体中文的电脑乱码 3 | chcp 65001 4 | setlocal enabledelayedexpansion 5 | 6 | :: 常量设置 7 | set PORT=5740 8 | 9 | :: 获取设备列表(跳过标题行) 10 | set deviceCount=0 11 | for /f "skip=1 tokens=1" %%a in ('adb devices') do ( 12 | if not "%%a"=="" ( 13 | :: 排除空行 14 | set /a deviceCount+=1 15 | set "device[!deviceCount!]=%%a" 16 | ) 17 | ) 18 | 19 | :: 检查是否有两部设备 20 | if %deviceCount% neq 2 ( 21 | echo 检测到的设备数量为 %deviceCount%,请同时连接两部手机! 22 | echo 已连接设备: 23 | for /L %%i in (1,1,%deviceCount%) do ( 24 | call :printDeviceName !device[%%i]! 25 | ) 26 | pause 27 | exit /b 28 | ) 29 | 30 | :: 获取两个设备的显示名称(格式:设备名:设备ID) 31 | call :getDeviceDisplay 1 deviceDisplay1 32 | call :getDeviceDisplay 2 deviceDisplay2 33 | 34 | echo. 35 | echo 请选择作为A手机(服务端)的设备: 36 | echo 1. %deviceDisplay1% 37 | echo 2. %deviceDisplay2% 38 | set /p choice=请输入数字 (1或2): 39 | 40 | if "%choice%"=="1" ( 41 | set "deviceA=%device[1]%" 42 | set "deviceB=%device[2]%" 43 | ) else if "%choice%"=="2" ( 44 | set "deviceA=%device[2]%" 45 | set "deviceB=%device[1]%" 46 | ) else ( 47 | echo 无效选择,退出. 48 | pause 49 | exit /b 50 | ) 51 | 52 | echo. 53 | echo 选择的A手机: %deviceA% 54 | echo 选择的B手机: %deviceB% 55 | 56 | echo. 57 | echo 正在设置端口转发... 58 | adb -s %deviceA% forward tcp:%PORT% tcp:%PORT% 59 | adb -s %deviceB% reverse tcp:%PORT% tcp:%PORT% 60 | 61 | echo. 62 | echo 端口转发设置完成! 63 | pause 64 | exit /b 65 | 66 | :printDeviceName 67 | :: 参数:设备ID,输出格式为:设备名:设备ID 68 | setlocal 69 | set "devID=%1" 70 | for /f "delims=" %%n in ('adb -s %devID% shell settings get global device_name 2^>nul') do ( 71 | set "devName=%%n" 72 | goto afterLoop2 73 | ) 74 | :afterLoop2 75 | if "%devName%"=="" set "devName=Unknown" 76 | echo %devName%:%devID% 77 | endlocal 78 | goto :eof 79 | 80 | :getDeviceDisplay 81 | :: 参数1:设备序号;参数2:返回变量名称 82 | setlocal 83 | set "devID=" 84 | set "devID=!device[%1]!" 85 | for /f "delims=" %%n in ('adb -s !devID! shell settings get global device_name 2^>nul') do ( 86 | set "devName=%%n" 87 | goto afterLoop 88 | ) 89 | :afterLoop 90 | if "!devName!"=="" set "devName=Unknown" 91 | endlocal & set "%2=%devName%:!device[%1]!" 92 | goto :eof 93 | -------------------------------------------------------------------------------- /script/launch-android-app.bat: -------------------------------------------------------------------------------- 1 | adb shell am start -n top.weixiansen574.hybridfilexfer/.MainActivity -------------------------------------------------------------------------------- /script/start-by-adb.bat: -------------------------------------------------------------------------------- 1 | chcp 65001 2 | java -jar -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 HybridFileXfer.jar -c adb 3 | pause -------------------------------------------------------------------------------- /script/start-by-network.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | chcp 65001 3 | set /p IPAddress=Please enter the phone's IP address: 4 | echo The IP address you entered is: %IPAddress% 5 | 6 | java -jar -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 HybridFileXfer.jar -c %IPAddress% 7 | pause 8 | -------------------------------------------------------------------------------- /手机对传.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/weixiansen574/HybridFileXfer/fd0755c90c99f43a2eb2dc7f62d399072e04da73/手机对传.jpg -------------------------------------------------------------------------------- /赞助名单.md: -------------------------------------------------------------------------------- 1 | # 赞助名单 2 | 3 | | Github账号 | 金额¥ | 日期 | 4 | | ------------------------------------------------------------ | ------ | ---------------------- | 5 | | [@long45343](https://github.com/long45343) | 10.00 | 2024-05-13 00:22:48 | 6 | | [匿名] | 2.00 | 2024年5月20日 06:55:08 | 7 | | [匿名] | 1.10 | 2024年6月8日 09:41:41 | 8 | | [无法识别的备注:双轨快传ID是[L07-31](https://github.com/L07-31)前有共15] | 14.37 | 2024年6月10日 01:28:51 | 9 | | [无法识别的备注:双轨快传ID是[L07-31](https://github.com/L07-31)前有共15] | 0.64 | 2024年6月10日 01:35:26 | 10 | | [@香菜和葱](https://github.com/825824004) | 6.66 | 2024-06-14 00:16:44 | 11 | | [匿名] | 10.00 | 2024-07-04 17:56:32 | 12 | | [@freemedom](https://github.com/freemedom) | 10.00 | 2024-07-25 16:18:52 | 13 | | [@freemedom](https://github.com/freemedom):希望解决issue35 36 | 10.00 | 2024-07-25 16:19:39 | 14 | | [@breathiness](https://github.com/breathiness) | 50.00 | 2024-07-28 14:21:47 | 15 | | [匿名] | 5.00 | 2024-09-07 00:35:07 | 16 | | [匿名] | 5.00 | 2024-09-22 20:55:57 | 17 | | [匿名] | 2.10 | 2025-01-02 13:31:51 | 18 | | [匿名] | 1.00 | 2025-01-20 13:50:07 | 19 | | [@cpp-deep-learning](https://github.com/cpp-deep-learning) | 10.00 | 2025-02-07 12:14:43 | 20 | | [@cpp-deep-learning](https://github.com/cpp-deep-learning) | 0.01 | 2025-02-07 12:15:24 | 21 | 22 | --------------------------------------------------------------------------------