Android - How to get a string of txt file from ftp? - java

My english isn't perfect, but I hope it helps some people that are trying to solve this problem ;-)
My Question
I'm learning Android programming yet and I hope you guys can help me.
I'm trying to get a string from a txt file, from a ftp server. My string is called "contents" and I'm trying to show it with my "texto" TextView.
I'm using FTPClient to acess the ftp server.
This is my method inside my MainActivity class:
public void get_txt() throws MalformedURLException {
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect("my.ftp.url", 21);
ftpClient.enterLocalPassiveMode();
ftpClient.login("my_user", "my_password");
InputStream inStream = ftpClient.retrieveFileStream("teste.txt");
InputStreamReader isr = new InputStreamReader(inStream, "UTF8");
String contents = isr.toString();
texto.setText(contents);
barra.setEnabled(false);
ftpClient.disconnect();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
Thanks, and I hope you can help me :)
EDIT 1: I forgot to mention. My app is running ok, the problem is that the TextView never changes.

The Final and Working Code (I hope it helps you)
Finally, after hours, I managed to get it right! For those who need the answer, here it is:
public class Principal extends AppCompatActivity {
public static TextView texto;
String contents;
ProgressBar barra;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_principal);
texto = (TextView) findViewById(R.id.texto);
TarefaDownload download = new TarefaDownload();
download.execute();
}
The code above is my MainActivity (I call it "Principal" here). I created only a TextView there, then I instaciated my AsyncTask class called "TarefaDownload". This class is a private class where all the logic to acess ftp is placed. Let's see this class code now.
private class TarefaDownload extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
}
#Override
protected Void doInBackground(Void... params) {
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect("my_ftp_link_here", 21);
ftpClient.enterLocalPassiveMode();
ftpClient.login("my_user_login_here", "my_password_here");
ftpClient.changeWorkingDirectory("/");
InputStream inStream = ftpClient.retrieveFileStream("teste.txt");
InputStreamReader isr = new InputStreamReader(inStream, "UTF8");
int data = isr.read();
contents = "";
while(data != -1){
char theChar = (char) data;
contents = contents + theChar;
data = isr.read();
}
isr.close();
ftpClient.disconnect();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
texto.setText(contents);
}
}
So, basically I was trying to read a single line string from a txt file called "teste". The method "doInBackground" runs everything in background (don't you say?), so all the code to access ftp must come there.
Then I created a String called "contents", started to read the chars (one per time) from the InputStreamReader and storing in the string. You must notice that the String contents is being used in this method, but it belongs to my MainActivity, so I can access it outside the AsyncTask class. Finally, when de doInBackground method finishes, the "onPostExecute" methos is called and set the text of my TextView to value of my String value.
That's all! You may notice that you must add a INTERNET permission on your Manifest file (or then you'll not be able to access the ftp server):
<uses-permission android:name="android.permission.INTERNET" />
And that's it, your app should be reading data from the ftp server!

Related

Cant connect to URL in java to copy raw JSON text

I'm writing a android trivia app that uses the Open Trivia DB to generate its questions. The problem I'm incurring is that I'm simply unable to connect to the generated API url and I'm not sure why.
I'm simply trying to pull the raw text from the URL and then sort it later, here is the relevant code:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button start = (Button)findViewById(R.id.button);
try {
getJSON();
}
catch (IOException e){
Log.d("CREATION","Something wrong");
}
}
private String getJSON()throws IOException{
URL trivia = new URL("https://opentdb.com/api.php?amount=10");
URLConnection yc = trivia.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(
yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
Log.d("CREATION",inputLine);
in.close();
return "";
}
}
The Stack trace from the errors I get comes back with this:
at edu.niu.students.z1802067.triviaapp.MainActivity.getJSON(MainActivity.java:59)
which is this line of code:
yc.getInputStream()));
How could I write this to simply get all the raw text from the JSON?
First of all you try make request with UI thread. It's blocking UI for a long time (time of request)
Try use thread like this:
new Thread(){
#Override
public void run() {
try {
getJSON();
}
catch (IOException e){
Log.d("CREATION","Something wrong: " + e, e);
}
}
}.start();
Better solution for reading data form API is use library like https://square.github.io/retrofit/
It simplifies the task and data processing

Calling methods after new Class.execute() crash, android studio

Basically, i have an app that uses JSON. I get the JSON in new HentData.execute(); and pass it to a string variable. But when I try to acutally do something with it my program crashes.
HentData extends AsyncTask, I know it gives me a JSON string that works
INSIDE oncreate()
new HentData().execute();
jsonToArray();
arrayToText();
This crashes
But when I run them like this it works, do I have to close the HentData class somehow?
protected void onPostExecute(String resultat){
json_string = resultat;
jsonToArray();
arrayToText();
}
This is my doInBackground()
protected String doInBackground(Void... voids){
try {
URL url = new URL(json_url);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
InputStream IS = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(IS));
StringBuilder sb = new StringBuilder();
while((json_string = bufferedReader.readLine())!=null){
sb.append(json_string+"\n");
}
bufferedReader.close();
IS.close();
httpURLConnection.disconnect();
return sb.toString().trim();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
But when I run them like this it works, do I have to close the HentData class somehow?
protected void onPostExecute(String resultat){
json_string = resultat;
jsonToArray();
arrayToText();
}
You don't have to close anything. This works because "async" in AsyncTask makes the code run in the background.
In other words,
new HentData().execute(); // Not waiting for result
jsonToArray(); // Continue on, even though there is no result yet --> error
arrayToText();
If you want a more flexible way to get results, see How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?
If you hate writing AsyncTasks (for HTTP methods), see Comparison of Android networking libraries: OkHTTP, Retrofit, and Volley

Client socket on android

I'm trying to send a single string from android to pc and after a bit of research on this site and others I've found out about sockets and how to use them. I have written the server program that can receive strings sent to it. Below is the code.
//static ServerSocket variable
private static ServerSocket server;
//socket server port on which it will listen
private static int port = 9021;
public static void main(String [] args) throws IOException, ClassNotFoundException{
server = new ServerSocket(port);
while(true){
System.out.println("Waiting for client request." + InetAddress.getLocalHost());
Socket socket = server.accept();
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
String message = (String)ois.readObject();
System.out.println("Message received: " + message);
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject("Hi Client: " + message);
ois.close();
oos.close();
socket.close();
if(message.equalsIgnoreCase("exit")){
break;
}
}
System.out.println("Shutting down serve");
server.close();
}
I have tested this using a pc client program that sends string and have confirmed that this server script works. I am trying to now implement the same concept in android but facing a lot of trouble mostly due to the fact that the tutorials online for this task is very outdated (2-3 years) so nothing works as expected. Can anyone tell me how to write a very simple android app in which a single string is sent over socket?
From what I can see in the logcat, the outdated tutorials on the internet are not working because android has apparently introduced in recent versions a very aggressive process manager which monitors the behaviour of threads and if there is any repeated thread actions, it shuts it down without notice.
Edit: As per a solution I have implemented an asynctask. But now the server is not receiving and says Address already in use. I think it is because of socket address in my android code. Please help!
public class MainActivity extends Activity {
private Button button;
private EditText message;
private TextView finalResult;
//InetAddress host;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
message = (EditText) findViewById(R.id.et_time);
button = (Button) findViewById(R.id.btn_do_it);
finalResult = (TextView) findViewById(R.id.tv_result);
/*
try {
host = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
AsyncTaskRunner runner = new AsyncTaskRunner();
String msg = message.getText().toString();
runner.execute(msg);
}
});
}
private class AsyncTaskRunner extends AsyncTask<String, String, String> {
Socket socket = null;
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
int clientport = 8080;
String resp;
#Override
protected String doInBackground(String... params) {
publishProgress("Sending...");
String msg = params[0];
for(int i=0;i<=5;i++){
//establish socket connection to server
try {
socket = new Socket( "100.69.73.16",clientport);
//write to socket using Objectouputstream
oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(msg+i);
oos.close();
socket.close();
Thread.sleep(100);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
resp = "Message has been sent";
return resp;
}
#Override
protected void onPostExecute(String result) {
finalResult.setText(result);
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(String... values) {
finalResult.setText(values[0]);
}
}
}
Ok so I solved the problem of 'address already used' by changing port number. Apparently the port number was being used by other programs on my laptop. So in retrospect for anyone checking on how to do this, you can use my above code and remember to change the port number in both codes to something similar. Also in my android code where the socket is opened, you can put in the local ip address (very important, google gives you external) for your computer.

preloader between activities - android java

I'm a android newbie.
I need to create some kind of preloader for the Activity. Right now I click the button say "Show company" and afterwards I go to the next activity where the data is loaded from serwer and shown inside. The problem is that (from what I understand) the activity is connecting with internet and until connections is done nothing is show. User must wait and then suddelny (after few seconds - varies) he gets new 100% ready page based on new activity.
The best for me would be sth like: create a loding animation that is shown until the activity is fully loaded. (that would solve problem everywhere)
Alternative would be: loading the new activity before connecting with the internet url. When its loaded it say sth default like "Loading data" until full text is downloaded from url that will replace the first text.
Here is the code I use to load text from URL.
try {
// Create a URL for the desired page
URL url = new URL(serwer_url);
// Read all the text returned by the server
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String str;
while ((str = in.readLine()) != null) {
// str is one line of text; readLine() strips the newline character(s)
Plain_str = Plain_str + str;
}
Log.i("Plain read str", Plain_str);
in.close();
} catch (MalformedURLException e) {
} catch (IOException e) {}
//end of reading file
//here is the anchor to the text in activity
TextView MainText = (TextView)findViewById(R.id.TextMain);
MainText.setText(Html.fromHtml(Plain_str.toString()));
You can use an AsyncTask like this:
protected class Mytask extends AsyncTask<Void, Void, String>{
#Override
protected String doInBackground(Void... params) {
String Plain_str= null;
try {
// Create a URL for the desired page
URL url = new URL(serwer_url);
// Read all the text returned by the server
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String str;
while ((str = in.readLine()) != null) {
// str is one line of text; readLine() strips the newline character(s)
Plain_str = Plain_str + str;
}
Log.i("Plain read str", Plain_str);
in.close();
} catch (MalformedURLException e) {
} catch (IOException e) {}
return Plain_str;
}
protected void onPostExecute(String str){
TextView MainText = (TextView)findViewById(R.id.TextMain);
MainText.setText(Html.fromHtml(str.toString()));
}
}
And then to execute the Task
new MyTask().execute();

How to correctly use parameters passed to an android thread?

I have an external .hash file which I tired reading as a simple remote text file:
private class getHash extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... params) {
String str = null;
try {
// Create a URL for the desired page
URL url = new URL(params[0]);
// Read all the text returned by the server
InputStream is = url.openStream();//The line it crashes on
InputStreamReader isr = new InputStreamReader(is);
BufferedReader in = new BufferedReader(isr);
str = in.readLine();
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return str;
}
#Override
protected void onPostExecute(String result) {
hash = result;
}
}
Then I call the thread :
getHash hashThread = new getHash();
hashThread.execute(new String[]{"http://www......................hash"});
During execution of the noted line in the class all stops are pulled and I get slapped by the classy Source not found crash.
LogCat gives this error:
W/dalvikvm(724): threadid=1: thread exiting with uncaught exception (group=0x40a13300)
Are you running this in debug mode or regular mode?
The source not found message would seem to indicate you are trying to step into code that has no source attached for it.
Also have you added
<uses-permission android:name="android.permission.INTERNET" />
to your AndroidManifest.xml?

Categories

Resources