Unable to connect to FTP in Android - java

I've checked the other answers and they didn't help me with this error. Maybe I'm doing something else wrong.
Here's my code:
void uploadPic() throws FileNotFoundException
{
FileInputStream fis = new FileInputStream(path);
FTPClient con = new FTPClient();
int bytesAvailable;
try
{
con.connect("ftp://ftp.drivehq.com/");
Toast.makeText(this, "Connected to FTP", Toast.LENGTH_SHORT).show();
if (con.login("x", "x"))
{
Toast.makeText(this, "Logged in", Toast.LENGTH_SHORT).show();
con.enterLocalPassiveMode(); // Active mode doesn't really work on Android
bytesAvailable = fis.available();
byte[] barray = new byte[bytesAvailable];
fis.read(barray);
ByteArrayInputStream in = new ByteArrayInputStream(barray);
boolean result = con.storeFile("/CameraUpload.jpg", in);
in.close();
if (result) Log.v("Upload Result", "Succeeded");
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
I've added INTERNET permission to my project.
The logcat shows these errors:
android.os.NetworkOnMainThreadException
W/System.err(17531): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1099)
W/System.err(17531): at java.net.InetAddress.lookupHostByName(InetAddress.java:391
I'm connected to the internet via Wifi.

That exception seems to be thrown when you try to perform network operations (such as FTP) from your main thread. This is not allowed for performance reasons (so that the application doesn't appear to lock up to the user, when performing an action which may take a while). Assuming you are using Honeycomb or higher, you would need to move the code that makes the connection into its own child thread.
http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html
http://developer.android.com/guide/practices/design/responsiveness.html

Most likely, this error means that your device cannot resolve ftp.drivehq.com to its IP address. I can't say for sure because you only pasted part of the error log. Make sure you have network connection and that your DNS is working correctly. See if you can connect to this same site via android browser, for example.

Related

NullPointerException when making XMPP connection through Smack 4.2.0

I intend to use Smack to send messages through Firebase CCS. I modified a simple CCS client for my Web App but when I try to make connection, it results in exception.
I am using Smack 4.2.0
Here is the process of connection.
1) The connection method which is in my client:
public void connect() throws XMPPException{
try{
config = XMPPTCPConnectionConfiguration.builder()
.setPort(Config.FCM_PORT)
.setHost("fcm-xmpp.googleapis.com")
.setXmppDomain("googleapis.com")
.setSecurityMode(/*Default; Explicit setting for emphasis*/SecurityMode.ifpossible)
.setSendPresence(true)
.setUsernameAndPassword(fcmServerUsername, mApiKey)
.setSocketFactory(SSLSocketFactory.getDefault())
.setDebuggerEnabled(mDebuggable)/* Launch a window with info about packets sent and received */
.build();
}
catch(XmppStringprepException e){
e.printStackTrace();
}
connection = new XMPPTCPConnection(config);
// Configuring Automatic reconnection
ReconnectionManager manager = ReconnectionManager.getInstanceFor(connection);
manager.setReconnectionPolicy(ReconnectionManager.ReconnectionPolicy.RANDOM_INCREASING_DELAY);
manager.enableAutomaticReconnection();
// Connect now then login
try{
connection.connect();
connection.login();
}
// TODO: Handle the exceptions if possible appropriately
catch(SmackException sme){
logger.severe(sme.getMessage());
sme.printStackTrace();
}
catch(IOException ioe){
logger.severe(ioe.getMessage());
ioe.printStackTrace();
}
catch(InterruptedException ie){
logger.severe("Connection got interrupted!!");
ie.printStackTrace();
}
}
2) I traced the exception and I got it here: (Smack's source)
At the line - HostAddress hostAddress = DNSUtil.getDNSResolver().lookupHostAddress(config.host, config.port, failedAddresses, config.getDnssecMode());
// AbstractXMPPConnection.java
protected List<HostAddress> populateHostAddresses() {
List<HostAddress> failedAddresses = new LinkedList<>();
if (config.hostAddress != null) {
hostAddresses = new ArrayList<>(1);
HostAddress hostAddress = new HostAddress(config.port, config.hostAddress);
hostAddresses.add(hostAddress);
}
else if (config.host != null) {
hostAddresses = new ArrayList<HostAddress>(1);
HostAddress hostAddress = DNSUtil.getDNSResolver().lookupHostAddress(config.host, config.port, failedAddresses, config.getDnssecMode());
if (hostAddress != null) {
hostAddresses.add(hostAddress);
}
} else {
// N.B.: Important to use config.serviceName and not AbstractXMPPConnection.serviceName
hostAddresses = DNSUtil.resolveXMPPServiceDomain(config.getXMPPServiceDomain().toString(), failedAddresses, config.getDnssecMode());
}
// Either the populated host addresses are not empty *or* there must be at least one failed address.
assert(!hostAddresses.isEmpty() || !failedAddresses.isEmpty());
return failedAddresses;
}
The exception is NullPointerException and I found that getDNSResolver() returns null. Of all the sources I have referenced, there wasn't anything related to DNS resolver as it is supposed to be internally handled by Smack. So my question is, have I missed out some crucial configuration or step in making the connection?
EDIT: I asked here because Smack is vast lib and there might some config someone knows that I might have missed. I am unable to set DNSResolver directly
EDIT : ANSWER UPDATE
This is NOT a bug in Smack's source as their Upgrade Guide for 4.2.0 explicitly mentions:
**
API Changes
**
Warning: This list may not be complete
Introduced ConnectionConfiguration.setHostAddress(InetAddress)
In previous versions of Smack,
ConnectionConfiguration.setHost(String) could be used to set the
XMPP service's host IP address. This is no longer possible due to the
added DNSSEC support. You have to use the new connection configuration
ConnectionConfiguration.setHostAddress(InetAddress) instead.
This seems to be a bug because I solved it by providing the Host Address (which was supposed to be inferred from {Host, Domain}). So, how did I know to provide the host address?
The trick lies here: (Smack' source)
// AbstractXMPPConnection.java
if (config.hostAddress != null) {
hostAddresses = new ArrayList<>(1);
HostAddress hostAddress = new HostAddress(config.port, config.hostAddress);
hostAddresses.add(hostAddress);
}
else if (config.host != null) {
hostAddresses = new ArrayList<HostAddress>(1);
HostAddress hostAddress = DNSUtil.getDNSResolver().lookupHostAddress(config.host, config.port, failedAddresses, config.getDnssecMode());
if (hostAddress != null) {
hostAddresses.add(hostAddress);
}
} else {
// N.B.: Important to use config.serviceName and not AbstractXMPPConnection.serviceName
hostAddresses = DNSUtil.resolveXMPPServiceDomain(config.getXMPPServiceDomain().toString(), failedAddresses, config.getDnssecMode());
}
You can see the if, else-if blocks here and since the exception arises in the else if (config.host != null) block, I provided hostAddress so that it never enters that block and it worked.
I know this is sort of a hack around the actual problem but this seems to be a bug in Smack 4.2.0 unless someone disproves me otherwise.
Bonus info: If after rectifying this problem, you get another exception in Base 64 encoding during login, refer to this - XMPP client using Smack 4.1 giving NullPointerException during login
Not sure in 4.2.0 but in 4.2.2 (and newer), you will need smack-resolver-dnsjava-4.2.2.jar to be in your classpath, smack calls DNSUtil which is included in the package, if the class doesn't exist it returns NullPointerException.
Hope this help!
David

Can we open channel without AID and control the power of embedded SE?

We are now developing a payment card with NXP NQ220 (has embedded SE, called eSE) on Android N. The platform is MTK. Now, we can interact with eSE using OMA (using org.simalliance.openmobileapi.jar). It works as expected.
I was wondering if there is any ways to open channel in session without AID? Besides, is there any ways to control the power of eSE(power-on and power-off) and reset eSE in some situations?
My investigation as follows:
About open channel without AID, I have found following sentences in page 16 of Open Mobile API specification V3.
(h)Method: Channel openLogicalChannel(byte[] aid, Byte P2)
Open a logical channel with the SE, selecting the applet represented by the >given AID. If the AID is null, which means no applet is to be selected on >this channel, the default applet is used. It's up to the SE to choose which >logical channel will be used.
However, if we set aid to null in openLogicalChannel(byte[] aid), following exception will be shows. What happens about it? Is the default applet or eSE have problems?
01-30 01:06:39.941 V/SmartcardService( 2587): OpenLogicalChannel Exception: Access Control Enforcer: no APDU access allowed!
01-30 01:06:39.947 E/SeControlClient( 3239): Error occured:
01-30 01:06:39.947 E/SeControlClient( 3239): java.lang.SecurityException: Access Control Enforcer: no APDU access allowed!
01-30 01:06:39.947 E/SeControlClient( 3239): at org.simalliance.openmobileapi.SEService.checkForException(SEService.java:255)
01-30 01:06:39.947 E/SeControlClient( 3239): at org.simalliance.openmobileapi.Session.openLogicalChannel(Session.java:295)
It seems there is no method in OMA to reset eSE. But I found reset() method in INxpNfcAdapterExtras. However, when I use INxpNfcAdapterExtras.reset(), it always return false. Following codes is how we get INxpNfcAdapterExtras.
private INxpNfcAdapterExtras getNxpNfcAdapterExtras() {
if (mNfcAdapter != null) {
try {
INxpNfcAdapter nxpNfcAdapter =
mNfcAdapter.getService().getNxpNfcAdapterInterface();
return nxpNfcAdapter.getNxpNfcAdapterExtrasInterface();
} catch (Exception e) {
Log.e(LOGTAG, "Exception occured:", e);
}
} else {
Log.e(LOGTAG, "Please initialize NfcAdapter first.");
}
return null;
}
About control the power of eSE, is it related to the platform? Can you give me some suggestions? Thank you very much.
Dont known
To access SE functions your application must be execute with owner of android device.
You could check this in : https://github.com/NXPNFCLinux/android_nxp-nci/blob/1d95fe24334fa12c9d9eccd1141f8739972c4288/aosp/packages/apps/Nfc/src/com/android/nfc/NfcService.java
The reset method check permission before:
public boolean reset(String pkg) throws RemoteException {
NfcService.this.enforceNfceeAdminPerm(pkg);
Bundle result;
boolean stat = false;
try {
stat = _nfcEeReset();
result = writeNoException();
} catch (IOException e) {
result = writeEeException(EE_ERROR_IO, e.getMessage());
}
Log.d(TAG,"reset" + stat);
return stat;
}
The check permission method:
public void enforceNfceeAdminPerm(String pkg) {
if (pkg == null) {
throw new SecurityException("caller must pass a package name");
}
NfcPermissions.enforceUserPermissions(mContext);
if (!mNfceeAccessControl.check(Binder.getCallingUid(), pkg)) {
throw new SecurityException(NfceeAccessControl.NFCEE_ACCESS_PATH +
" denies NFCEE access to " + pkg);
}
if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
throw new SecurityException("only the owner is allowed to call SE APIs");
}
}
To execute your app with device owner, you could follow my anwser here:
Device Admin API, how to be a device owner?
I'm not sure about what you mean "control the power of eSE". If it's on/off eSE, then eSE is integrated with NFC chip so if you disable NFC in Android eSE will be power off.
I have found another way to solve this issue. It used NXP's own class NxpNfcAdapterExtrasService.
1.I still don't know why the exception happens when we open channel use the default Applet(without AID). But, with the method in NxpNfcAdapterExtrasService, we can establish connection with eSE.
2.About the second question. The codes is right but the way of how to use INxpNfcAdapterExtras.reset() is wrong. This method will return true only when you do something with eSE. Like transmit and execute APDU commands. So you can use this method when you want to disconnect the connection with eSE.
3.About the third question, I don't know whether the openUicc()/closeUicc() method can control the eSE power. But, it seems this two method works as expected.

Bluetooth communication between Processing Desktop and Android(Not Processing)

What I'm doing is communication between
Desktop(Windows 8) Processing(2.2.1) Application <---- Android application(Not made by Processing, it's made on Android Studio)
I need to send data to desktop from android application (one side communication).
From android..
First, I'm getting already paired device. It means that before executing both application, I will pair desktop and android device already.
Bluetooth connection and sending outstream is on child thread.
Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
Log.i(TAG, device.getName() + "\n" + device.getAddress());
targetDevice = device;
break;
}
}else{
Log.i(TAG, "No paired device found!");
}
And then, I connect it
BluetoothSocket tmp = null;
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
tmp = targetDevice.createRfcommSocketToServiceRecord(MY_UUID);
Method m = targetDevice.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
tmp = (BluetoothSocket) m.invoke(targetDevice, 1);
} catch (Exception e) {
Log.e(TAG, "create() failed", e);
}
btSocket = tmp;
if (btSocket != null){
// Socket is created
// try to connect the socket
BluetoothConnectionThread thread = new BluetoothConnectionThread(btSocket);
thread.start();
}
From logcat(Log.i), I can see connection is successfully established. It seems that there is no problem on android side.
I'm using Serial Port Protocol UUID which is
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
And from Android side, it's completely ready to write any byte[].. and when I press dummy button on android, device sends dummy bytes to outputstream. I think it has no problem here on Android side..
Now, on desktop processing(Windows 8, processing 2.2.1 - I HAVE TO USE processing 2.0, there is no other option for some reason.), I have no any clue what I have to now.. I searched in google a lot but I could not find any clue. Now, I'm trying to use processing Serial library like
println(Serial.list());
but it gives nothing... So, I tried to initialize Serial object by
Serial port = new Serial(this, "/dev/rfcomm0", 115200);
but it gives error
Error opening serial port /dev/rfcomm0:Port busy
Is there any other way to read socket buffer(instream) which comes from Android on processing desktop?
I am sure that this is not bluetooth driver issue because I installed the recentest driver for my desktop(Qualcomm Atheros AR3012 Bluetooth 4.0 + HS)
Just for reference..desktop is actually laptop with bluetooth(ASUS UX21E) and Android device is Galaxy Tab S(267.2mm, Octa-Core 2560x1600).
I think I have not enough knowledge about bluetooth... Please lead me to some way...

Apache MINA server closes active UDP "session" after 60s

My client-server app works with Apache MINA at both, client and server sides. Sending data via UDP works OK, but after a minute server closes the connection (or MINA's way - "session") and stops answering.
The strange part is that the connection is active the whole time. Client is sending data every 1000ms and server answers to it with the same data. I've found a MINA's mechanism to destroying inactive sessions ExpiringMap, it's got a default value for session's time-to-live public static final int DEFAULT_TIME_TO_LIVE = 60; but I haven't found a way how to change it or better, update time-to-live for sessions.
Imho the time-to-live should update automatically with every incoming packet but I couldn't find a thing why isn't it my server doing. Should I say explicitly that I don't want it to destroy the session yet or what?
My code is quite similar to MINA's tutorials:
SERVER
IoAcceptor acceptor = new NioDatagramAcceptor();
try {
acceptor.setHandler( new UDPHandler() );
acceptor.bind( new InetSocketAddress(RelayConfig.getInstance().getUdpPort()) );
acceptor.getSessionConfig().setReadBufferSize( 2048 );
acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, IDLE_PERIOD );
System.out.println("RELAY ["+RelayConfig.getInstance().getId()+"]: initialized!");
} catch (IOException e) {
System.out.println("RELAY ["+RelayConfig.getInstance().getId()+"]: failed: "+e.getLocalizedMessage());
//e.printStackTrace();
}
CLIENT
NioDatagramConnector connector = new NioDatagramConnector();
connector.getSessionConfig().setUseReadOperation(true);
handler = new UDPHandler();
connector.setHandler(handler);
connector.getSessionConfig().setReadBufferSize(2048);
// try to connect to server!
try {
System.out.println("Connecting to " + relayIP + ":" + port);
ConnectFuture future = connector.connect(new InetSocketAddress(relayIP, port));
future.addListener(new IoFutureListener<IoFuture>() {
public void operationComplete(IoFuture future) {
ConnectFuture connFuture = (ConnectFuture)future;
if( connFuture.isConnected() ){
UDPClient.setSession(future.getSession());
Timer timer = new Timer("MyTimerTask", true);
timer.scheduleAtFixedRate(new MyTimerTask(), 1000, 1000); // My message is written here every 1000ms
} else {
log.error("Not connected...exiting");
}
}
});
future.awaitUninterruptibly();
} catch (RuntimeIoException e) {
System.err.println("Failed to connect.");
e.printStackTrace();
System.exit(1);
} catch (IllegalArgumentException e) {
System.err.println("Failed to connect. Illegal Argument! Terminating program!");
e.printStackTrace();
System.exit(1);
}
For any additional info please write in comments.
EDIT: Unfortunately I don't have access to that server any more, but problem was not solved back then. If there's anybody else who has the same problem and solved it, let us know.
I did some research and found the link below. You may need to explicitly set the disconnect option to false, but there is also another option to reset the timeout option. A timeout of 30000 is 30 seconds, 60000 is 60 seconds, etc... These solutions are from MINA2. It was not clear if you were using that or an older version. From this you should be able to add the call that implements a specific set of options when you open the UDP port.
MINA2 Documentation

Getting error "Can't read input file" on production server but not locally

I make a POST to a request with a File included in the request body.
In my method I retrieve this File
if(request.body.file("imageFile").getOrElse(null) != null) {
request.body.file("imageFile").map{ case FilePart(key, name, contentType, content) =>
try{
val in:InputStream = new BufferedInputStream(new ByteArrayInputStream(content))
image = ImageIO.read(in)
} catch {
case e => Logger.debug(e.printStackTrace.toString); throw new Exception(e.getMessage)
}
}
}
If a File is included in the request body it tries to get it, else it just tries to get a file from S3.
else {
try{
val in:InputStream = new BufferedInputStream(new ByteArrayInputStream(S3Storage.retrieveS3File("facebook.jpg").content))
image = ImageIO.read(in)
} catch {
case e:IOException => Logger.debug("Failed to retrieve facebook image"); throw new IOException(e.getMessage)
}
All this works fine when I run it on my computer, but when I check in this and test it on the amazon server the image = ImageIO.read(in) gives me an error; Can't read input file!.
For me this makes no sense since the file is either in the request body or it's grabbed from a S3 bucket.
I've debugged this code and in the production environment there is a file available there when the "read" is done.
Why cannot the file be read from the production environment?
regards
One suggestion would be not to swallow the original exception and stack trace.
Use constructor new Exception(message, catchedException) in your catch blocks.

Categories

Resources