Project name: FTPDownloadFile
FTPconnection
class implementationpackage com.example.ftpdownloadfile; import android.util.Log; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPReply; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.SocketException; import java.net.UnknownHostException; public class FTPconnection { private native String getHostname(); private native String getUsername(); private native String getPassword(); private static String FTPHostName = ""; private static final int FTPPort = 21; private static String FTPUsername = ""; private static String FTPPassword = ""; public FTPconnection() { FTPHostName = getHostname(); FTPUsername = getUsername(); FTPPassword = getPassword(); } // Reference: https://stackoverflow.com/a/24605713/6667035 public Boolean downloadAndSaveFile(String filename, File localFile) throws IOException { String LOG_TAG = "FTPconnection_download"; FTPClient ftp = null; try { ftp = new FTPClient(); ftp.connect(FTPHostName, FTPPort); Log.d(LOG_TAG, "Connected. Reply: " + ftp.getReplyString()); ftp.login(FTPUsername, FTPPassword); Log.d(LOG_TAG, "Logged in"); ftp.setFileType(FTP.BINARY_FILE_TYPE); Log.d(LOG_TAG, "Downloading"); ftp.enterLocalPassiveMode(); OutputStream outputStream = null; boolean success = false; try { outputStream = new BufferedOutputStream(new FileOutputStream( localFile)); success = ftp.retrieveFile(filename, outputStream); } finally { if (outputStream != null) { outputStream.close(); } } return success; } finally { if (ftp != null) { ftp.logout(); ftp.disconnect(); } } } }
ftpdownloadfile.cpp
#include <jni.h> #include <string> extern "C" JNIEXPORT jstring JNICALL Java_com_example_ftpdownloadfile_FTPconnection_getHostname(JNIEnv *env, jobject thiz) { std::string output = "Hostname"; return env->NewStringUTF(output.c_str()); } extern "C" JNIEXPORT jstring JNICALL Java_com_example_ftpdownloadfile_FTPconnection_getUsername(JNIEnv *env, jobject thiz) { std::string output = "Username"; return env->NewStringUTF(output.c_str()); } extern "C" JNIEXPORT jstring JNICALL Java_com_example_ftpdownloadfile_FTPconnection_getPassword(JNIEnv *env, jobject thiz) { std::string output = "Password"; return env->NewStringUTF(output.c_str()); }
ExecutorService
for new threadExecutorService executor = Executors.newSingleThreadExecutor(); executor.submit(() -> { String threadName = Thread.currentThread().getName(); showToast(threadName, Toast.LENGTH_SHORT); FTPconnection ftpConnect = new FTPconnection(); final String LOG_TAG = "executor"; try { String filename = "test.txt"; Log.v(LOG_TAG,"Preparing to download " + filename); var result = ftpConnect.downloadAndSaveFile(filename, Paths.get(getApplicationInfo().dataDir + "/" + filename).toFile()); if (result == false) { Log.v(LOG_TAG,"Fail to download " + filename + "!"); } else { Log.v(LOG_TAG,"Download " + filename + " successfully!"); } } catch (Exception ex) { ex.printStackTrace(); } });
User permission setting
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.ftpdownloadfile"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.FTPDownloadFile"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> </manifest>
build.gradle
plugins { id 'com.android.application' } android { compileSdk 31 defaultConfig { applicationId "com.example.ftpdownloadfile" minSdk 26 targetSdk 31 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" externalNativeBuild { cmake { cppFlags '' } } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 } externalNativeBuild { cmake { path file('src/main/cpp/CMakeLists.txt') version '3.18.1' } } } dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') // https://mvnrepository.com/artifact/commons-net/commons-net implementation group: 'commons-net', name: 'commons-net', version: '20030805.205232' implementation 'androidx.appcompat:appcompat:1.46.1' implementation 'com.google.android.material:material:1.511.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.3'4' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3'5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.45.0'1' }