So I have run into a bit of an issue, I wanted to use an FTP transfer for my android app using java, sounded simple enough, so I got it working fine in normal java using the Apache-commons library, but when I attempted to use the same method in android java I ran into an error that log cat traces back to, I need to be able to connect to a pre-existing FTP server and be able to upload and download files, from it. I have read several things saying that "You need Internet permissions" so I added
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
to my "AndroidManifest.xml" and I still run into the same issue, I then read another thing where it said you need to use an a-sync method because you can't do internet operations in the main visual thread, so I tried that, and that absolutely didn't work, and android-studio just screamed at me that the "A-sync method" was deprecated, I have asked on several discord communities got no response except for some guy who wanted to proclaim that "FTP is insecure" I do not care about that, I have my reasons and needs for FTP transfers and I just want to know how to get this working. Any help will be immensely appreciated and I am still relatively new to java and android development so a more dumbed down easier to comprehend answer would be very nice of you to my smooth brain, but I will take almost anything that will work at this point. And yes I have
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
added to my "androidmanifest.xml" aswell
Snippet of my code in a different method from the onCreate method that gets called by the clicking a button
String server = "exampleserver.com";
int port = 21;
String user = "username";
String pass = "password";
FTPClient ftpClient = new FTPClient();
try{
ftpClient.connect(server, port);
ftpClient.login(user, pass);
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
File firstLocalFile = new File("/test/test.txt");
String firstRemoteFile = "test.txt";
InputStream inputStream = new FileInputStream(firstLocalFile);
ftpClient.storeFile(firstRemoteFile, inputStream);
}catch(IOException e) {
e.printStackTrace();
}
List of My imports
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
I also have the pop up to get read and write permissions
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE
, Manifest.permission.READ_EXTERNAL_STORAGE}, PackageManager.PERMISSION_GRANTED);
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.INTERNET
, Manifest.permission.INTERNET}, PackageManager.PERMISSION_GRANTED);
}
and I have tried it with and without the INTERNET Grant line or whatever it makes no difference, and of course I do put in the real file names and username and password and domain in my actual code just not showing it here Log cat errors:
2021-08-17 18:28:57.501 6978-6978/com.example.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.myapplication, PID: 6978
java.lang.IllegalStateException: Could not execute method for android:onClick
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:414)
at android.view.View.performClick(View.java:6930)
at android.widget.TextView.performClick(TextView.java:12773)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1119)
at android.view.View$PerformClick.run(View.java:26211)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:7000)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:441)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1408)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:409)
at android.view.View.performClick(View.java:6930)
at android.widget.TextView.performClick(TextView.java:12773)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1119)
at android.view.View$PerformClick.run(View.java:26211)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:7000)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:441)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1408)
Caused by: android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1450)
at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:102)
at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:90)
at java.net.InetAddress.getByName(InetAddress.java:743)
at org.apache.commons.net.SocketClient.connect(SocketClient.java:212)
at com.example.myapplication.MainActivity.click(MainActivity.java:57)
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:409)
at android.view.View.performClick(View.java:6930)
at android.widget.TextView.performClick(TextView.java:12773)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1119)
at android.view.View$PerformClick.run(View.java:26211)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:7000)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:441)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1408)
line 57 is this piece of code that can be seen above: (click function is the method that gets called to do the FTP transfer when you hit a button)
ftpClient.connect(server, port);