ReadInputDiscretesResponse error (Jamod,Android) - android

I'm using the library Jamod and I have trouble reading the record, what I want is to read only the record number 300 PLC I'm connected, but I get read error (enters the catch). Thanks for your help
package com.JR.scada;
import java.net.InetAddress;
import net.wimpi.modbus.Modbus;
import net.wimpi.modbus.io.ModbusTCPTransaction;
import net.wimpi.modbus.msg.ReadInputDiscretesRequest;
import net.wimpi.modbus.msg.ReadInputDiscretesResponse;
import net.wimpi.modbus.msg.ReadMultipleRegistersResponse;
import net.wimpi.modbus.net.TCPMasterConnection;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class Main extends Activity{
TextView text, depurar;
EditText IP;
Button boton;
int i=0;
TCPMasterConnection con = null; //the TCP connection
ModbusTCPTransaction trans = null; //the Modbus transaction
InetAddress addr = null; //direccion del esclavo
int port = Modbus.DEFAULT_PORT;//puerto por defecto 502
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.lblRegistro);
IP = (EditText) findViewById(R.id.txtIp);
depurar = (TextView) findViewById(R.id.txtdepurar);
boton = (Button)findViewById(R.id.btnVerRegistro);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
protected void onStop() {
super.onStop();
//Close the TCP connection
con.close();
}
public class conectar extends AsyncTask<String,String,Integer>{
ReadInputDiscretesRequest req = null; //the request
ReadInputDiscretesResponse res = null; //the response
int startReg;
protected void onPreExecute() {
try {
//IP address;
addr = InetAddress.getByName("212.170.50.238");
} catch (Exception e) {
Log.d("MODBUS","IP error", e);
}
}
protected Integer doInBackground(String... urls) {
try {
// Open the connection
con = new TCPMasterConnection(addr);
con.setPort(port);
con.connect ();
try {
startReg = 300;
// Prepare the request
req = new ReadInputDiscretesRequest (startReg, 1);
// Prepare the transaction
trans = new ModbusTCPTransaction(con);
trans.setRequest(req);
// execute the transaction
trans.execute();
// get the response
res = (ReadInputDiscretesResponse) trans.getResponse ();
} catch (Exception e) {
Log.d("MODBUS", "Error in reading/writing");
return 1;
}
} catch (Exception e) {
Log.d("MODBUS","connection error", e);
return 1;
}
return 0;
}
protected void onPostExecute(Integer bytes) {
if(con.isConnected()){
depurar.setText("conecta");
}
text.setText("Digital Inputs Status=" + res.getDiscretes ().toString () );
}
}
public void onClick(View v) {
// int startReg;
conectar conectamos = new conectar();
conectamos.execute("hola");
}
error:
08-21 10:01:57.554: D/MODBUS(3322): Error in reading/writing

Without knowing more about the modbus configuration on your slave PLC, my first suggestion is to try a different value for startReg, and see if the error persists. This will rule out problems with your Java.
Some test numbers that should work: 0,1,7,8
They may not all work, but at least one of them should return successfully.
If none of them return successfully, there may be a problem on the PLC configuration, or a problem with your request code.
If one of the test numbers is successful, you should post your results. If so, this means that you are attempting to access a memory location that does not exist on the PLC. If you access undefined PLC memory locations, often the PLC will abort the request (it does not just send back '0').
Followup remarks:
If you find that your code works when using different values for startReg, but not for 300, the reason has to do with memory mapping on the PLC, and this can be different for each brand/model of PLC (post your PLC brand/model if available).
You say in your question 'record 300'. When working with PLC, you usually don't refer to memory as a record. Are you trying to access Bit 300, Byte 300, Word 300, DoubleWord 300?
The real question you need to be asking, is 300 the actual modbus address you want to read, or is 300 how the PLC address is mapped (such as the 300th I/O slot, not necessarily the 300th WORD). It may be required to convert between octal, decimal, and hexidecimal addresses. Or, you may need to re-index an address (some PLCs like to start counting at 1, but generally modbus starts counting at 0).
Perhaps you meant to read BIT 300 (not record 300), which would then be 12th BIT in the 18th WORD, so it would look like this:
//
startReg = 17;
// Prepare the request
// Your 300th bit should be the last value returned.
req = new ReadInputDiscretesRequest (startReg, 12);
The different values I suggested for startReg are meant to help you discover how your PLC Inputs are mapped into modbus addresses by your Java library. This might help with number conversions.

If you keep getting exceptions in your catch block, you might want to find out more about the error.
Try changing this line from your original code:
try {
//...
} catch (Exception e) {
Log.d("MODBUS", "Error in reading/writing");
return 1;
}
into this:
try {
//...
} catch (Exception e) {
Log.d("MODBUS", e.getMessage() );
return 1;
}
Hopefully the exception will tell you more about exactly why its failing. Post those results.
If you are getting a NULL message, you might try using a debugger to manually inspect your connection instance.

Related

Send continuous bluetooth stream from Android to Arduino

I'm working on a simple vehicle project, made with Arduino Uno and controlled by an Android App.
My matter is to send continuous stream from the app to my bluetooth module (HC-06) on Arduino.
I did it with onTouch events and a new thread called from my main activity, but something is obviously wrong because the app seems to send each command as i want it to do, but the Arduino waits until the finger is off the button and receives all data (from action.down to action.up) at a time.
To understand :
I update a small string like this "1255090" each time a command button is action.down or action_move, convert it to bytes and send it via bluetooth.
If i briefly click on the button, Arduino will receive the correct string "1255090", but if i maintain my finger on the button, Arduino waits for the string, and when i release the button, Arduino receives for example "125509012540901253090125209012510901252090" (depending on how long i clicked).
Android activity (partial)
drive.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent m) {
if (m.getAction() != MotionEvent.ACTION_UP) {
accelerer(); // inscreases the speed
str_flux(); // constructs the string
byte[] bytes = new byte[0];
try { bytes = flux.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); }
sendReceiveBT.write(bytes); // calls the thread's method
} else{ralentir();}
return true;
}
});
Thread
package com.*.vehicle.util;
import android.bluetooth.BluetoothSocket;
import android.util.Log;
import java.io.IOException;
import java.io.OutputStream;
public class SendReceiveBytes implements Runnable {
private BluetoothSocket btSocket;
private OutputStream btOutputStream = null;
String TAG = "SendReceiveBytes";
public SendReceiveBytes(BluetoothSocket socket) {
btSocket = socket;
try { btOutputStream = btSocket.getOutputStream(); } catch (IOException streamError) { Log.e(TAG, "Error when getting input or output Stream"); }
}
public void run() {
byte[] buffer = new byte[1024];
int bytes;
}
public void write(byte[] bytes) {
try {
btOutputStream.write(bytes); // Send the bytes to Arduino
btOutputStream.flush(); // don't know if it really does something...
Log.e(TAG, "SUCCESS !");
}
catch (IOException e) {
Log.e(TAG, "Error when writing to btOutputStream");
}
}
}
Arduino loop
void loop() {
s = Serial.readString(); // 1255090
if (s!=""){
Serial.println(s);
bt_direction = s.substring(0,1).toInt();
bt_speed = s.substring(1,4).toInt();
bt_angle = s.substring(4,7).toInt();
s = "";
} else{
if (bt_speed>0){
for(int i=bt_speed;i>=0;i--){bt_speed--;}
}
else{ bt_speed = 0; }
}
if (bt_direction==1){bt_dir = true;} else{bt_dir = false;}
if (bt_speed==0){stop_motor();} else{dc_motor(bt_speed, bt_dir);}
Serial.println(bt_direction);
servo_turn(bt_angle);
}
If I am getting you correctly, you can easily handle it using multiple states.
For example,
State1: 123456: is for tap,
State2: 123457: is for press & hold,
State3: 123458: is for release,
And so on.
And in you ui detect whether user is tapping or press and hold.
If press and hold , instruct arduino to do something until receives release.
In this way you can even handle the situation without continuously sending bit, And as per my understanding you don't need this.
Correct me if I am wrong.
Thanks !!!

Cannot start VPN using Toyvpn

I'll try to be as descriptive as possible
I'm new to android and i'm making an android application
In that application i'd like to be able to see the address of the HTTP requests going OUT from the mobile (On what website they are heading).
So i've looked around and i found out that to do that , I need to use a VPN and android 4.0+ has a VPNService supplied from google implemented using ToyVPNService
So i got this service and started changing in it so i can use it without the need of using a server
I'd like to work the VPN as follows:
1-Capture the HTTP requests
2-Read their destination
3-Resend them back to their way
So i took the VPNService and i started modifying it so that i don't need an actual server
Here's the code i'm using
package com.example.testingservice;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.net.VpnService;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.widget.Toast;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.util.Enumeration;
public class SO1 extends VpnService implements Handler.Callback, Runnable {
private static final String TAG = "ToyVpnService";
private Handler mHandler;
private Thread mThread;
private ParcelFileDescriptor mInterface;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// The handler is only used to show messages.
if (mHandler == null) {
mHandler = new Handler(this);
}
// Stop the previous session by interrupting the thread.
if (mThread != null) {
mThread.interrupt();
}
// Start a new session by creating a new thread.
mThread = new Thread(this, "ToyVpnThread");
mThread.start();
return START_STICKY;
}
#Override
public void onDestroy() {
if (mThread != null) {
mThread.interrupt();
}
}
#Override
public boolean handleMessage(Message message) {
if (message != null) {
Toast.makeText(this, message.what, Toast.LENGTH_SHORT).show();
}
return true;
}
#Override
public synchronized void run() {
Log.i(TAG,"running vpnService");
try {
runVpnConnection();
} catch (Exception e) {
e.printStackTrace();
//Log.e(TAG, "Got " + e.toString());
} finally {
try {
mInterface.close();
} catch (Exception e) {
// ignore
}
mInterface = null;
mHandler.sendEmptyMessage(R.string.disconnected);
Log.i(TAG, "Exiting");
}
}
private boolean runVpnConnection() throws Exception {
configure();
FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());
// Allocate the buffer for a single packet.
ByteBuffer packet = ByteBuffer.allocate(32767);
// We keep forwarding packets till something goes wrong.
while (true) {
// Assume that we did not make any progress in this iteration.
boolean idle = true;
// Read the outgoing packet from the input stream.
int length = in.read(packet.array());
if (length > 0) {
Log.i(TAG,"************new packet");
System.exit(-1);
while (packet.hasRemaining()) {
Log.i(TAG,""+packet.get());
//System.out.print((char) packet.get());
}
packet.limit(length);
// tunnel.write(packet);
packet.clear();
// There might be more outgoing packets.
idle = false;
}
Thread.sleep(50);
}
}
public String getLocalIpAddress()
{
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
Log.i(TAG,"****** INET ADDRESS ******");
Log.i(TAG,"address: "+inetAddress.getHostAddress());
Log.i(TAG,"hostname: "+inetAddress.getHostName());
Log.i(TAG,"address.toString(): "+inetAddress.getHostAddress().toString());
if (!inetAddress.isLoopbackAddress()) {
//IPAddresses.setText(inetAddress.getHostAddress().toString());
Log.i(TAG,"IS NOT LOOPBACK ADDRESS: "+inetAddress.getHostAddress().toString());
return inetAddress.getHostAddress().toString();
} else{
Log.i(TAG,"It is a loopback address");
}
}
}
} catch (SocketException ex) {
String LOG_TAG = null;
Log.e(LOG_TAG, ex.toString());
}
return null;
}
private void configure() throws Exception {
// If the old interface has exactly the same parameters, use it!
if (mInterface != null) {
Log.i(TAG, "Using the previous interface");
return;
}
// Configure a builder while parsing the parameters.
Builder builder = new Builder();
String SS=getLocalIpAddress();
builder.setMtu(1500);
// builder.addAddress("10.0.0.2", 24);
builder.addAddress(SS, 24);
// builder.addAddress(SS,24);
builder.addRoute("0.0.0.0",0);
try {
mInterface.close();
} catch (Exception e) {
// ignore
}
mInterface = builder.establish();
}}
The problem is this line
mInterface = builder.setSession("GITVPN").setConfigureIntent(mConfigureIntent).establish();
the Establish returns NULL and i can't seem to get it working
I'm thinking there is a problem with the addresses
I'd like to work it that there's no server , and there would be a tunnel that reads the packets
I've seen some other post that said i should make the addresses to 10.0.0.2 instead of external ips ( 192.168.x.x) and i should add route (0.0.0.0,0)
However the descriptor file keeps returning null and i can't seem to fix it
Any help will be appreciated , and sorry if this sounded that it was repeated but i'm super stuck and you guys are my only hope
You can't run the VpnService and establish a VPN connection without having a server that you communicate with and forwards the traffic to the internet.
Check the IP address you assigned to the interface, it should not be the same as other adapters.
What the builder operated on is a TUN device, which is created for VPN service.
So, IP address of the TUN should be proper set.
Make the address conflict with others is not a good idea.
Also, Step 3 you mentioned is not quite easy as Android not support raw socket.
just to revive an old thread...
VpnService requires a users interaction to start and won't work without it
the ToyVpnClient puts a button on the screen that the user has to click and once that's done, the Builder method will return the interface
so, steps to make it work are;
1. build a button on your app
2. onclick of that button, call VpnService.prepare(this); (this = your app context)
3. Builder.establish() will now return a VPN interface

commumicating between windows app and android app

I'm sorry if this is a very general question but I don't know where to start so I'm looking for ideas.
I have a windows app (music score editing) and I'm currently porting it to Andriod which is coming along well.
I would like to add the feature than documents created in the windows app can be sent to the users android tablet. I was wondering, how would I write some kind of listener on Android that the windows side could open a socket or something to and send data across to it, assuming both are on the same local network.
thanks
I think sending files directly over a local network isn't the best approach. You are prone to many user complaints that the sharing isn't working.. and this will mostly be due to their own network configuration issues.
Why not use a service like DropBox to implement file sharing?
Services like DropBox offer simple API that can be used in apps in order to save files into a remote folder, and read files from a remote folder.
This way, users will not have to be in the same network at all.. and most of the heavy-lifting of implementing file sharing will be done by a service that is focused around that.
Addition:
If you don't want to require an account for a separate service like DropBox, consider this approach: Implement a very simple DropBox-like service on your own web server. Make a simple script that will allow users to upload a file to your server anonymously via HTTP. After upload, they will receive a 5 digit id for this file, or some other link they could share. When using this id or link from the 2nd app, the file could be downloaded (again via HTTP). If you delete files automatically from the server after a few hours, you will not run out of space.
You can implement such a service with about 20 lines of PHP code. And the required apps code is extremely simple (since it only relies on HTTP). If you're worried about the costs of a web server, you can get one from about $5/month or even use a free service like Google App Engine (free if your bandwidth+space requirements are low).
Code example for the file upload. Downloading should be simple enough to do alone. Regarding the periodical file delete - the obvious approach is cron but I think it's easy to manage without it. Whenever you accept a new upload (in the PHP script), go over all the downloads and delete old ones.
i wrote a small thing so my windows app can find an instance of my android app running on the local network, here it is. this is the android code first
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import android.os.AsyncTask;
import android.util.Log;
public class TabSyncServer extends AsyncTask<Void, Void, Void> {
ServerSocket mServerSocket = null;
Socket mSocket = null;
DataInputStream mDataInputStream = null;
DataOutputStream mDataOutputStream = null;
#Override
protected void onPreExecute() {
try {
mServerSocket = new ServerSocket(2112);
//System.out.println("Listening :2112");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
protected Void doInBackground(Void... args) {
byte[] bytebuf = new byte[1024];
while (true) {
try {
mSocket = mServerSocket.accept();
mDataInputStream = new DataInputStream(mSocket.getInputStream());
mDataOutputStream = new DataOutputStream(mSocket.getOutputStream());
Log.d("TabSyncServer", "ip: " + mSocket.getInetAddress());
mDataInputStream.read(bytebuf);
String str = new String(bytebuf, "UTF8");
Log.d("TabSyncServer", "message: " + str);
if(str.contains("Hello Android")) {
Log.d("TabSyncServer", "sending reply");
mDataOutputStream.writeBytes("Hello Windows");
}
//
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (mSocket != null) {
try {
mSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (mDataInputStream != null) {
try {
mDataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (mDataOutputStream != null) {
try {
mDataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
and the windows MFC code
void CMainFrame::OnBrowseMobile() {
CMobileSync* con = new CMobileSync();
CString ipaddr_base;
int my_last_digit;
if(!con->getMyIP(ipaddr_base, my_last_digit)) {
setMobilePath("Can't find local network");
return;
}
for(int i=1 ; i<98 ; i++) {
if(i==my_last_digit)
continue; // don;t check self
CString ipaddr; ipaddr.Format("%s.%d", ipaddr_base, i);
bool res = con->ConnectToHost(ipaddr);
if(res) {
res = con->SendMsg ("Hello Android");
if(res) {
TRACE1("send ok %s\n",ipaddr.GetBuffer());
#define RD_BUF_LEN 80
char buffer[RD_BUF_LEN];
if(con->ListenOnPortBlocking(buffer, RD_BUF_LEN)) {
if(strncmp(buffer, "Hello Windows", 12)==0) {
TRACE1("reply ok %s", buffer);
setMobilePath(ipaddr);
con->CloseConnection ();
return;
}
}
} else {
TRACE("send FAILED\n");
}
}
con->CloseConnection ();
}
setMobilePath("No TabTrax on local network");
}
#include "stdafx.h"
#include <winsock.h>
#include "MobileSync.h"
#define TTPORT 2112
bool CMobileSync::getMyIP(CString& ipaddr_front, int& ipaddr_lastdigit)
{
char szBuffer[1024];
#ifdef WIN32
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 0);
if(::WSAStartup(wVersionRequested, &wsaData) != 0)
return false;
#endif
if(gethostname(szBuffer, sizeof(szBuffer)) == SOCKET_ERROR)
{
#ifdef WIN32
WSACleanup();
#endif
return false;
}
struct hostent *host = gethostbyname(szBuffer);
if(host == NULL)
{
#ifdef WIN32
WSACleanup();
#endif
return false;
}
//Obtain the computer's IP
unsigned char b1, b2, b3, b4;
b1 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b1;
b2 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b2;
b3 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b3;
b4 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b4;
ipaddr_front.Format("%d.%d.%d", b1, b2, b3);
ipaddr_lastdigit = b4;
#ifdef WIN32
WSACleanup();
#endif
return true;
}
//CONNECTTOHOST – Connects to a remote host
bool CMobileSync::ConnectToHost(const char* IPAddress)
{
//Start up Winsock…
WSADATA wsadata;
int error = WSAStartup(0x0202, &wsadata);
//Did something happen?
if (error)
return false;
//Did we get the right Winsock version?
if (wsadata.wVersion != 0x0202)
{
WSACleanup(); //Clean up Winsock
return false;
}
//Fill out the information needed to initialize a socket…
SOCKADDR_IN target; //Socket address information
target.sin_family = AF_INET; // address family Internet
target.sin_port = htons (TTPORT); //Port to connect on
target.sin_addr.s_addr = inet_addr (IPAddress); //Target IP
mSocket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); //Create socket
if (mSocket == INVALID_SOCKET)
{
return false; //Couldn't create the socket
}
//Try connecting...
if (connect(mSocket, (SOCKADDR *)&target, sizeof(target)) == SOCKET_ERROR)
{
return false; //Couldn't connect
}
return true; //Success
}
//CLOSECONNECTION – shuts down the socket and closes any connection on it
void CMobileSync::CloseConnection ()
{
//Close the socket if it exists
if (mSocket)
closesocket(mSocket);
mSocket=0;
WSACleanup(); //Clean up Winsock
}
int CMobileSync::SendMsg (char* szpText, int buflen)
{
if(buflen==0)
buflen = strlen(szpText);
int ret = send(mSocket, szpText, buflen, 0);
TRACE1("CMobileSync::SendMsg sent %d bytes\n", ret);
return ret;
}
WSADATA w;
//LISTENONPORT – Listens on a specified port for incoming connections
//or data
bool CMobileSync::ListenOnPortBlocking(char* buffer, int buflen)
{
//Now we can start listening (allowing as many connections as possible to
//be made at the same time using SOMAXCONN). You could specify any
//integer value equal to or lesser than SOMAXCONN instead for custom
//purposes). The function will not //return until a connection request is
//made
// listen(s, SOMAXCONN);
memset(buffer, 0, sizeof(buffer)); //Clear the buffer
int iTimeout = 1600;
setsockopt( mSocket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&iTimeout, sizeof(iTimeout));
//Put the incoming text into our buffer
int ret = recv (mSocket, buffer, buflen-1, 0);
//Don't forget to clean up with CloseConnection()!
if(ret != SOCKET_ERROR)
return true;
int err = WSAGetLastError();
return false;
}
its not tested extensively but it is running
this maybe useful to someone

Android throws exception when sending UDP packet

I'm trying to send a UDP packet to a server to see if it is online. I have made a stand alone app to do exactly that and it works without a problem but when putting the code in the app and calling the function it throws an exception when it goes to actually send the packet. I have done a lot of research and I can't find any reason why. I replaced the IP with a fake one because I don't want to post the actual IP. Thanks for the help in advanced.
import java.io.IOException;
import java.net.*;
import android.app.Activity;
public class CheckStatus extends Activity {
//Check if the server is online
public static boolean check() {
try {
byte[] receiveData = new byte[1024];
InetAddress address = InetAddress.getByName("11.11.11.11");
//create socket
DatagramSocket clientSocket = new DatagramSocket();
//set timeout
clientSocket.setSoTimeout(1000);
//send packet
DatagramPacket p = new DatagramPacket(Integer.toBinaryString(0x0006000000).getBytes(), 5, address, 44462);
clientSocket.send(p);//throws exception here
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
clientSocket.close();
return true;
} catch (Exception e) {
return false;
}
}
}
When printing the exception i got "android.os.NetworkOnMainThreadException"
Declare this asyncTask in the activity and call your check() method from there.
EDIT:
private class CheckStatusTask extends AsyncTask<Object, Object, Boolean> {
protected Boolean doInBackground(Object... arg0) {
boolean flag = check();
return flag;
}
protected void onPostExecute(Boolean flag) {
// use your flag here to check true/false.
}
}
And make this call :
new CheckStatusTask().execute();
Reference :
Painless threading

Error while trying to download a file via ftp on android

I am an amateur in android coding.
I am trying to setup an android app with the ability to download a file from an ftp server. While running the code on the android 2.2 emulator, i am able to connect to the ftp server but the downloading part is showing an error. LogCat gives "download failed".
package com.ftconnect.down;
import java.io.FileOutputStream;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import org.apache.commons.net.ftp.*;
public class FTPConnectActivity extends Activity {
/** Called when the activity is first created. */
public FTPClient mFTPClient = null;
public boolean mConnect;
public boolean mDownload;
public boolean mDisconnected;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mConnect = ftpConnect("xxx.xxx.xxx.xxx", "admin",
"123456", 21);
mDownload = ftpDownload("xxx.xxx.xxx.xxx/ftp.mp3", "/sdcard");
mDisconnected = ftpDisconnect();
}
public boolean ftpConnect(String host, String username, String password,
int port) {
try {
mFTPClient = new FTPClient();
// connecting to the host
mFTPClient.connect(host, port);
Log.d("ftpConnectApp", "Connecting to " + host);
// now check the reply code, if positive mean connection success
if (FTPReply.isPositiveCompletion(mFTPClient.getReplyCode())) {
// login using username & password
boolean status = mFTPClient.login(username, password);
return status;
}
} catch (Exception e) {
Log.d("ftpConnectApp", "Error: could not connect to host " + host);
}
return false;
}
public boolean ftpDownload(String srcFilePath, String desFilePath) {
boolean status = false;
try {
FileOutputStream desFileStream = new FileOutputStream(desFilePath);
;
status = mFTPClient.retrieveFile(srcFilePath, desFileStream);
desFileStream.close();
return status;
} catch (Exception e) {
Log.d("ftpConnectApp", "download failed");
}
return status;
}
public boolean ftpDisconnect() {
try {
mFTPClient.logout();
mFTPClient.disconnect();
return true;
} catch (Exception e) {
Log.d("ftpConnectApp",
"Error occurred while disconnecting from ftp server.");
}
return false;
}
}
I have setup the internet and write external permission in the android manifest file. Should i include any other permissions?
Also, let me know if there is any changes to be made to the code above. Is the destination address as '/sdcard' correct?
Thanks in advance.
You need to add Exception variable in your log message. You may also want to print full stack trace of the problem using:
e.printStackTrace();
Generally /sdcard should work, however it is more reliable to request SD card location using Environment object. See more details about file storage on android in
link
Also, let me know if there is any changes to be made to the code above. Is the destination address as '/sdcard' correct?
At the very least you should use /sdcard/filename.ext although this would only be OK for testing purposes if you are sure that /sdcard is a valid root directory.
To do things correctly, use getExternalFilesDir to find the correct path to the external storage 'files' directory that can be used for 'private' files for your own app. See the example code in that link for how to use it. You'll need to provide a filename for the output stream not just a path to a directory.
This may not be the answer to your problem but simply using...
FileOutputStream desFileStream = new FileOutputStream(desFilePath);
...when desFilePath is a directory, i.e., /sdcard, and not a file is guaranteed to fail.
Use
mFTPClient.enterLocalActiveMode();
after login

Categories

Resources