XMPP SMACK file receiving not working on android - android

I am unable to recive the file, which I am transfering from SPARK client.
I am using ASMACK jar Library so it's not possible to get into the library.
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
if (sdm == null){
sdm = new ServiceDiscoveryManager(connection);
sdm.addFeature("http://jabber.org/protocol/disco#info");
sdm.addFeature("jabber:iq:privacy");
}
// new ServiceDiscoveryManager(connection);
FileTransferNegotiator.setServiceEnabled(connection, false);
FileTransferManager manager = new FileTransferManager(connection);
manager.addFileTransferListener(new FileTransferListener() {
public void fileTransferRequest(FileTransferRequest request) {
Log.d("", "allows file...");
if (request != null) {
// Accept it
IncomingFileTransfer transfer = request.accept();
try {
// String pathsd = Environment.getExternalStorageDirectory().toString();
String path = "/sdcard/"+ request.getFileName();
transfer.recieveFile(new File(path));
// transfer.recieveFile(new
// File(request.getFileName()));
System.out.println("File " + request.getFileName() + "Received Successfully");
// Log.d("", "rece: " + request.getFileName());
// Log.d("", "path: " + request.getFileName());
// InputStream input = transfer.recieveFile();
} catch (XMPPException ex) {
Log.d("", "er: " + ex);
}
} else {
Log.d("", "reject file...");
request.reject();
}
}
});

Don't know what version of Smack your asmack is based on, but there is a known issue with file transfer in Smack, which both asmack and Spark are based on.

Beems asmack build process is well documented and also the sources are open for everyone.
Your code looks right, but why do you set this
FileTransferNegotiator.setServiceEnabled(connection, false);
to false?
File transfer in XMPP is a rather complex topic. There are various methods (at least 4), to get a file from one resource to another. As you provided no further details I can only give you general device on how to debug this:
Enable connection debug in smack, which will print out and log all XMPP packets that go in and out. Trace the XMPP stanzas that relate to the file transfer and make sure they behave as specified in the XEPs. This may provides a hint about whats going wrong.

Related

ftp4j - Too many connections exception

I am creating a sync service which will copy files to ftp folder selected by user. When i run the service, it connects with ftp and check whether file at android local storage is available at ftp or not and if not, it uploads. Below is my code.
FTPClient ftpClient = new FTPClient();
ftpClient.setPassive(true);
if (!ftpClient.isConnected()) {
ftpClient.connect(server, port);
}else {
Log.i(TAG,"FTP already connected");
}
if (!ftpClient.isAuthenticated()) {
ftpClient.login(username, password);
}else {
Log.i(TAG,"FTP already Logged In");
}
ftpClient.changeDirectory(rfolderpath);
String[] files = ftpClient.listNames();
if (Arrays.asList(files).contains(filename)) {
Log.i(TAG, filename + " Already Found in FTP, Skipping");
} else {
Log.i(TAG, "Sending Go Ahead For Upload");
File file = new File(filepath);
Log.i(TAG, "Uploading File: " + filename);
ftpClient.upload(file);
ftpClient.logout();
ftpClient.disconnect(true);
}
The code works fine for first 8 files and then i start getting exception of too many connections (8) from this IP and my sync terminates.
Here is Error text:
it.sauronsoftware.ftp4j.FTPException [code=421, message= Too many connections (8) from this IP]
Can someone help me how to handle this scenario.
I changed the logic of uploading files. Now created one ftp connection under AsyncTaskLoader and with that upload all files w/o error.

Unexpected status line: ICY 200 OK for URL openStream() method?

According to changes for kitakt 4.4 there were some problems with playing shoutcast streams (those returning "ICY" instead of "HTTP/1.x" response).
So solution for kitkat was to reregister "icy" protocol prefix in JVM once before we opened a stream by this:
try {
java.net.URL.setURLStreamHandlerFactory( new java.net.URLStreamHandlerFactory(){
public java.net.URLStreamHandler createURLStreamHandler( String protocol ) {
Log.d( LOG, "Asking for stream handler for protocol: '" + protocol + "'" );
if ("icy".equals( protocol )) return new com.spoledge.aacdecoder.IcyURLStreamHandler();
return null;
}
});
}
catch (Throwable t) {
Log.w( LOG, "Cannot set the ICY URLStreamHandler - maybe already set ? - " + t );
}
I have problem with open audio stream to make it register. After I call url.opnestream(stream) I got exception:
java.net.ProtocolException: Unexpected status line: ICY 200 OK
How could I fix it?
Here is sample of registering audio, so far what I did..
try {
URL url = null;
url = new URL(u);
inputStream = url.openStream();
startTime = System.currentTimeMillis();
Boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
String fileName = File.separator + "radio_" + "recording_" + channelMetadata.replaceAll("\\W", "") + System.currentTimeMillis();
if(isSDPresent)
{
outputSource = Environment.getExternalStorageDirectory() + fileName;
}
else
{
outputSource = Environment.getDataDirectory() + fileName;
}
if(contentType.equals("audio/aacp"))
fileOutputStream = new FileOutputStream(outputSource + ".acc");
else if(contentType.equals("audio/mpeg"))
fileOutputStream = new FileOutputStream(outputSource + ".mp3");
else
fileOutputStream = new FileOutputStream(outputSource + ".nieznany_format");
int bytesRead = 0;
int bytes;
while (((bytes = inputStream.read()) != -1) && isRecording) {
fileOutputStream.write(bytes);
bytesRead++;
stopTime = System.currentTimeMillis();
long seconds = (Math.abs(startTime-stopTime));
int minutes = 1000 * 60 * 60;
if(minutes<=seconds)
{
Log.d("xxx", "recording task exceed stopped");
break;
}
}
inputStream.close();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
isRecording = false;
}
isRecording = false;
return null;
Various changes were made for Android 4.4, and it seems that the non-standard ShoutCast ICY header is not supported by Android.
It seems though that the good people of OkHttp fixed the issue (issue 1 and issue 2) already a few days ago.
What you can do, is simply use OkHttp lib directly in your application and by that you'll use the newer OkHttp version (the one with the fix) and not the one shipped with Android (where you'll have to wait for an OS update).
This will also fix it for your application running on other devices that might suffer from that issue.
The answer of Assaf Gamliel worked for me. For those not familiar with this, you have to download the last .jar from okHttp and the .jar from the dependency okio . Add them to your libs directory and connect like this :
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(mediaUrl)
.build();
Response response = client.newCall(request).execute();
InputStream stream = response.body().byteStream();
The easiest fix ever.
which is 100% working for me,
for shoutcast , change your URL ex. "http://192.168.1.1:9292" to "icy://192.168.1.1:9292"
and you'll be fine.

Empty Android log file using FileHandler()

I'm trying to set up a log handler to output the Android log to file to external storage. The code below creates the log file, but no output is sent to the file, so something is obviously wrong with how the handler is configured. Or, perhaps this arrangement cannot be expected to work at all?
The function is called in onCreate() from the main activity.
private void logToFile(String path) {
try {
// Get package name
String packageName = MainActivity.class.getPackage().getName();
String logfileName = path + "/" + packageName + ".log";
Logger logger = Logger.getLogger(packageName);
logger.setLevel(Level.FINE);
FileHandler fileTxt = new FileHandler(logfileName);
SimpleFormatter formatterTxt = new SimpleFormatter();
fileTxt.setFormatter(formatterTxt);
logger.addHandler(fileTxt);
Toast.makeText(this, "Logging to " + logfileName, Toast.LENGTH_LONG).show();
} catch (IOException e) {
Log.d(TAG, e.getMessage());
}
Log.i(TAG, "logging to filesystem enabled");
}
To write to the logger declared above (and, thus, the attached handler which writes to a file), the following should be used instead of Log.i(TAG, "message")
private static final Logger logger = Logger.getLogger(TAG);
public void someFunction() {
logger.info("message")
}
These log messages will also appear in logCat/debugger, with the supplied TAG.
P.S. Java logging makes my head hurt...
I was frustrated at having to use Logger instead of standard Logcat Log.d(), Log.e(), etc. so I started using this Frankenstein's monster solution of reading from Logcat into a LogRecord and saving that using FileHandler.
This means you can limit the log file size easily, and retain your detailed Android logs.
But this isn't going to give you continuous output to file. If you don't mind pressing a button or calling it once a session though, then it shouldn't really matter since Logcat is constantly updated anyway.
(I strongly recommend calling from a non-UI thread.)
FileHandler fh=null;
String name;
if ( 0 == Environment.getExternalStorageState().compareTo(Environment.MEDIA_MOUNTED))
name = Environment.getExternalStorageDirectory().getAbsolutePath();
else
name = Environment.getDataDirectory().getAbsolutePath();
name += "/yourapp/yourapp";
try {
fh = new FileHandler(name, 1024*1024, 7, true); //Limit to 7 x 1MB files.
fh.setFormatter(new SimpleFormatter());
//Try to read Logcat.
try {
//Dumps the entire logcat to std output.
Process processD = Runtime.getRuntime().exec("logcat -v long -d");
BufferedReader bufferedReaderD = new BufferedReader(new InputStreamReader(processD.getInputStream()));
String lineD;
while ((lineD = bufferedReaderD.readLine()) != null){
//Send to the file handler.
fh.publish(new LogRecord(Level.ALL, lineD));
}
//Clear the logcat storage. Don't feel like rewriting old records.
Process processC = Runtime.getRuntime().exec("logcat -c");
} catch (IOException e) {
Log.e(TAG, "Could not get Logcat logs.");
e.printStackTrace();
}
} catch (Exception e) {
Log.e("MyLog", "FileHandler exception", e);
} finally {
if (fh != null)
fh.close();
}

Dropbox Api AccessToken Changed

I am developing an android application that has the potential to provide large amount of statistical information. I want to save this data on my dropbox to be analyzed later.
So I used the AuthActivity to get the key and secret for my own account, which I then hardcoded to get an AcessTokenPair instance:
AcessTokenPair tokenPair = new AccessTokenPair("key", "secret");
mDBApi.getSession().setAccessTokenPair(tokenPair);
I then send the file to my dropbox using the AsyncTask below:
private class SendToDropbox extends AsyncTask<String, Void, String> {
#SuppressWarnings("deprecation")
#Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
String timestamp = new Date().toString();
FileInputStream inputStream = null;
DisplayMetrics dm = new DisplayMetrics();
win.getDefaultDisplay().getMetrics(dm);
double x = Math.pow(dm.widthPixels / dm.xdpi, 2);
double y = Math.pow(dm.heightPixels / dm.ydpi, 2);
double screenInches = Math.sqrt(x + y);
File sdcard = new File(Environment.getExternalStorageDirectory()
.getPath());
File session = null;
try {
session = File.createTempFile("analytics_" + timestamp, ".txt", sdcard);
if (session.exists()) {
PrintStream ps = new PrintStream(session);
ps.println("Screen Size: " + screenInches);
ps.println("Device: " + android.os.Build.MODEL);
ps.println("Carrier: " + android.os.Build.BRAND);
ps.println("Locale: " + Locale.getDefault().toString());
ps.println("OS: " + android.os.Build.VERSION.SDK);
ps.println("${EOF}");
ps.checkError();
ps.close();
inputStream = new FileInputStream(session);
com.dropbox.client2.DropboxAPI.Entry newEntry = mDBApi
.putFile("Analytics" + File.separator
+ session.getName(), inputStream,
session.length(), null, null);
if (session.delete()) {
} else {
session.deleteOnExit();
}
Log.i("DbExampleLog", "The uploaded file's rev is: "
+ newEntry.rev);
} else {
Log.e("DropBoxFile", "SD NOT MOUNTED!!");
}
} catch (DropboxUnlinkedException e) {
// User has unlinked, ask them to link again here.
Log.e("DbExampleLog", "User has unlinked.");
} catch (DropboxException e) {
Log.e("DbExampleLog", "Something went wrong while uploading.");
} catch (FileNotFoundException e) {
Log.e("DbExampleLog", "File not found.");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
}
}
}
return null;
}
The only problem with this code is that it only works a few weeks, maybe a month before the access token changes. This means I would have to manually update the apk every few weeks, which isn't very feasible. Instead I would like to store the keys on a website or online file that I can access via http.
Are there any free programs that DO NOT require account access and allow you to upload and edit .txt files on the web?
Access tokens do not currently expire, though that may change in future. You'd need to be very careful never to unlink your app from the account used to generate the token, though, since that would invalidate the token which is hard-coded into your app.
I can't recommend this, though, for security reasons. A token embedded into your app can be discovered by someone reverse-engineering the app. And anyone with that token can not only read, but also write to the Dropbox (or App folder) to which the token has access, and by doing so they might screw up the other users of your app.
From the Dropbox Best Practices: Best Practices
Your app should take precautions in case of revoked access. Access tokens may be disabled by the user (from the account page), revoked by Dropbox administrators in cases of abuse, or simply expire over time.
In the case where a token is no longer authorized, the REST API will return an HTTP Error 401 Unauthorized response. The iOS SDK detects 401s for you and will call the sessionDidReceiveAuthorizationFailure: method on the session's delegate to notify you that the authorization was revoked. The Android, Python, Ruby, and Java SDKs will all raise an exception on server errors that you can catch and inspect. Re-authenticating is typically all that is necessary to regain access.
So the Access Token can surely change over time. You just must be flexible enough to deal with that.

How to get last created file from an FTP directory?

I first want to get a list of files stored in an FTP directory and then get the name of last created file using timestamp. And I'm getting an alert box: Activity is not responding. After checking logcat entry, I notice that the code never reach line :
Log.e("FTP", "number of filenames: " + count);
But I get to Log.e("FTP", "Connexion successful "); So connexion to the server seems ok.
It Seems like something going wrong out there. Can someone help me deal with it. Or show me a simple way to get the last created file from an the FTP server director?
FTPClient ftpClient = new FTPClient();
try
{
ftpClient.connect(InetAddress.getByName(Fonctions.address), Integer.parseInt(Fonctions.port));
if (ftpClient.login(Fonctions.login, Fonctions.pass))
{
Log.e("FTP", "Connexion successful ");
String workDir = ftpClient.printWorkingDirectory();
//Log.e("FTP", "workdir:" + workDir);
int count = ftpClient.listNames().length;
Log.e("FTP", "number of filenames: " + count);
FTPFile [] dossier = new FTPFile[count];
FTPFile back = new FTPFile();
dossier = ftpClient.listDirectories("Sarelo_FTP");
back = dossier[0];
Log.e("FTP", "Avant boucle " + back);
int buf = 0;
for (int i=0;i<(dossier.length) - 1;i++)
{
for (int j=1;j<dossier.length;j++)
{
buf = back.getTimestamp().compareTo(dossier[j].getTimestamp());
if (buf == -1)
back = dossier[j];
}
}
Log.e("FTP", "fichier final le plus récent: " + back.getName());
}
else{
Log.e("Restore FTP", "Error while connecting to FTP server");
}
}
catch(IOException e)
{
String title = "Error connecting to FTP server";
String msg = "Please check your parameters and connexion info: login, password,port number";
f.alert(c, title, msg).show();
Log.e("Restore FTP", "Error while connecting to FTP server", e);
}
P.S: I can't get the list of files in the directory so, I don't know if my code to retrieve the last created file is working. Any help on that would also be appreciated.
[Edit] This is my AsyncTask to retrieve the list of files in the directory. But it's still not working. I'm not getting Application Not Responding anymore, but It not seems to do anything else. Execution get stuck at the same point (can't reach Log.e("FTP", "number of filenames: " + count); )
class getFilesFromFtp extends AsyncTask
{
#Override
protected String doInBackground(Object... params)
{
int count = 0;
try
{
Log.e("FTP", "avant names: " + count);
count = ftpClient.listNames().length;
Log.e("FTP", "names: " + count);
handler.sendMessage(handler.obtainMessage());
}
catch (IOException e) {
Log.e("FTP", "Error getting number of files ", e);
}
return null;
}
}
Thanks for help.
You must not execute long running code on UI thread. Thia blocks UI redraw and event handling. It also produces ANR.
You should run it in the background thread, preferably via 'AsyncTask'.
First problem solved. I just needed to activate FTP data connection passive mode like that:
ftpClient.enterLocalPassiveMode();
before line int count = ftpClient.listNames().length;.
Hope this will help other people. Thanks to #Peter Knego driving me to AsynkTask. I learned something new. :)

Categories

Resources