Apache Ftp server integration with Android - android

I am working on integrating Apache FTP server to my Android app.
Follow the instructions here ( Embedding FtpServer in 5 minutes): http://mina.apache.org/ftpserver-project/embedding_ftpserver.html.
However, with all the codes included and the jar files imported to my android project, I got two major errors:
1. App crash upon ftp server start claiming class not found
2. Dalvik error 1
Tried every method by researching all related problems and the solution is to keep the minimal subset of the jar files that are listed in the (Embedding FtpServer in 5 minutes) instruction and make the code compile. Since there are not many jar files so I just did some try and error to get my minimal subset.
After that I use some new code to start the ftp server(here is the link): writing a java ftp server
However I couldn't connect because it says missing user.properties file. I download ftpserver-1.0.6-src source code and put the user.properties file into my android sdcard to make the ftp start. I put the user.properties file in the assets folder first, then copy it to the sdcard by using some code.
Now everything seems to work. However, I am not able to use anonymous login as my user name and password is set using:
BaseUser user = new BaseUser();
user.setName("test");
user.setPassword("test");
If I don't set it, the code won't compile.
Log in as anonymous user is the last part I have to do.
Another trivial thing is when I ftp to my android server, it won't allow me to download the files as it returns no permission error.
Any suggestions are welcome. Thank you

I've have had the same problem, so I've created my custom new users.properties file.
Here it is the code:
File files=new File(filepath + "/users.properties");
if (!files.exists()) {
try {
files.createNewFile();
} catch (IOException e) {
Log.e(TAG, "Errore nella creazione del file di log", e);
e.printStackTrace();
}
}
userManagerFactory.setFile(files);
userManagerFactory.setPasswordEncryptor(new SaltedPasswordEncryptor());
UserManager um = userManagerFactory.createUserManager();
BaseUser user = new BaseUser();
user.setName("xxx");
user.setPassword("yyy");
user.setHomeDirectory("/mnt/sdcard");
List<Authority> auths = new ArrayList<Authority>();
Authority auth = new WritePermission();
auths.add(auth);
user.setAuthorities(auths);
try {
um.save(user);
} catch (FtpException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}

Related

How to access files on a local server in android?

I need to access files on a local sever, and obtain their path for use in a File object.
I don't think I need to use HttpURLConnection for this purpose, do I?
Also, File file = new File(IPAddress) doesn't work.
Where IPAddress looks something like smb://192.168.1.xxx.
Will file:///192.168.1.xxx work for IPAddress?
I'm not able to find a solution on the internet where both accessing a local server and listing its files is achieved.
So, how do I get file paths from a local server for performing File operations?
Edit 1:
By local server I mean a computer on my network on which I have a shared folder.
And I'm building an app that can access that folder and contents in it and do something with them.
I am facing problems fetching file paths to that shared folder content.
Thanks everyone who helped...
My answer might help someone.
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("", username, password);
// username and password which you use for logging into your Windows PC
SmbFile network;
try {
network = new SmbFile("smb://servername or IPAddress", auth);
for (SmbFile node : network.listFiles()) {
// network path is now contained in 'node'
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (SmbException e) {
e.printStackTrace();
}
You'll have to add<uses-permission android:name="android.permission.INTERNET" />in your AndroidManifest.xml before the <application> tagandActivityCompat.requestPermissions(this /*context*/, new String[]{Manifest.permission.INTERNET}, MY_PERMISSIONS); in your Activity.java for getting access to Internet on API target 23 (Android 6.0) and above.
Download and include in your project jcifs-x.x.xx.jar for SmbFile and NtlmPasswordAuthentication Class, from here.

Google Drive API - download quota exceeded

I'm getting an error:
The download quota for this file has been exceeded
This is a response from the drive api. I'm trying to download a file simply via following url:
String url = "https://www.googleapis.com/drive/v2/files/" + media.getId() + "?alt=media\n"
My file is a few MBs big and I just can't download it. I'm using scribe and oauth2, I create a request, sign it and send it. The response shows me that the signature works, but I don't know why I always get the above error response from google...
Other things like retrieving a list of all my files and my user work just fine and work multiple times as well...
Since you're using Android, why not try to call it using the Java API client, as discussed in the Download Files section of the documentation.
private static InputStream downloadFile(Drive service, File file) {
if (file.getDownloadUrl() != null && file.getDownloadUrl().length() > 0) {
try {
// uses alt=media query parameter to request content
return service.files().get(file.getId()).executeMediaAsInputStream();
} catch (IOException e) {
// An error occurred.
e.printStackTrace();
return null;
}
} else {
// The file doesn't have any content stored on Drive.
return null;
}
}
Another alternative is to use the webContentLink to retrieve the download URL.
Hope this helps!
Log in multcloud
Add Cloud (Google Drive) & Login and Allow Drive
select the file and Share get public url

How to show progress while upload file to Cloudinary in Android?

I implemented the uploading function the file to Cloudinary.
Cloudinary cloudinary = new Cloudinary(Constants.CLOUDINARY_URL);
try {
FileInputStream is = new FileInputStream(new File(filePath));
Uploader uploader = cloudinary.uploader();
Map map = uploader.upload(is, new HashMap());
return map;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Now I would like to show the uploading percent in progress bar while upload.
But I can't find any callback function to get uploading percent.
Please help me.
Thanks.
cprakashagr answer actually works wonders. Just to elaborate on his answer, you will need to download the latest cloudinary library off github by doing this:
git clone https://github.com/cloudinary/cloudinary_java.git
Then you will have to make the changes according to his link:
https://github.com/cloudinary/cloudinary_java/pull/41
You cannot use Android Studio to make these changes as this is a maven project so you will need to use another IDE, like IntelliJ for example.
This is how I made the changes:
You will need to add on the class: UploadCallback
You will need to replace the class Uploader with his class: https://github.com/cprakashagr/cloudinary_java/blob/master/cloudinary-core/src/main/java/com/cloudinary/Uploader.java
Once you have done this, go into the main folder of your cloudinary_java, and then enter into Terminal. Go and type in mvn install and press enter. You will see that mvn will build the jars for the different folders in your directory. After the build is complete, if you navigate into the cloudinary-core folder for example, you will see the cloudinary-core jar.
You must copy the cloudinary-core jar from the folder and add it into your android project "libs" folder in the root of your android project. Once you have done that and it appears there, right click on the jar in Android Studios and click "Add as Library" so that android studios will add it as a dependency.
The cloudinary-android jar does not need to be added as a jar as you can grab a copy off gradle. Your final gradle file should look something like this:
compile('com.cloudinary:cloudinary-android:1.2.2') {
exclude module: 'cloudinary-core'
}
compile files('/Users/XXX/Documents/myApp/libs/cloudinary-core-1.4.2-SNAPSHOT.jar')
Rebuild your android studio project and you will see that the UploadCallback is now an object you can use in your android project. This is the way you know your jar build was successfully modified.
Now inside a service class, add your code for cloudinary direct upload. You will need to put the code inside a service class because you cannot do network operations on a UI thread and you will get an error if you tried:
Map config = new HashMap();
config.put("cloud_name", "XXX");
Cloudinary mobileCloudinary = new Cloudinary(config);
Map map = null;
try {
map = mobileCloudinary.uploader()
.uploadLarge(this,
intent.getSerializableExtra(getString(R.string.file)),
ObjectUtils.asMap("public_id", 123),
"tags", "myphoto",
"folder", "mylibrary",
"unsigned", true,
"upload_preset", "XXX"),
51200);
} catch (IOException e) {
e.printStackTrace();
}
String imageUrl = map.get("url").toString();
Timber.e("imageUrl " + imageUrl);
You must set the buffer to be large enough (but not too large) to make sure your callback is actually called. When I first tried this code out, I set the buffer to something really large, like 200000000, and the callback was not called because the upload would have happened all in one go. If you set it to a small value, like 2048, the callback will be called regularly however, the upload will become really slow. It is up to you to determine an adequate size which will work well for your app. For me it was 51200 which means for every 50kb of the file which is uploaded, a callback will occur.
Once it is working, you will need to transmit the progress information from the service class back to your activity class so you can display the progress on screen. I use a messageHandler to do so. This is the message method in my service class:
public void sendMessage(float progress) {
Message message = Message.obtain();
message.arg1 = Math.round(progress);
try {
messageHandler.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
This is my messageHandler on my activity class:
public class MessageHandler extends Handler {
#Override
public void handleMessage(final Message message) {
Timber.e("transfer: " + message.arg1);
}
}
The callback is not implemented from the cloudinary team yet. Though there have been few works around.
Check this link.
You need to import or build new JARs from the cloudinary source. For that, either you use this repository or make required changes to their original repository.
Let me know if you have some questions.
EDIT: On how to use it
Import these two cloudinary sources in your Android project (src/java dir):
Cloudinary Core Lib Source
Cloudinary Android Lib Source
Do changes as per my pull request.
And call the method uploadLarge as per the changed signature. Like:
cloudinary.uploader().uploadLarge(UploadCallback : uploadCallback, File : file, Map : options, int : bufferSize);
For buffer size, please assure you use at least 5242881. This is the limitation from cloudinary server. The minimum packet needs to be 5.001 MB at least.

Robotium - Write to file in eclipse workspace or computer file system

I'm running some tests using Robotium on an Android application that interacts with a web-portal.
I'd like to save some information to file; for example I need to save the id of the username I created from the app and I want to make it read from Selenium to run tests on web-portal to verify a webpage for that user has been created.
Is it possible?
Could someone suggest me a solution or a work-around?
This is an example of code, but it doesn't work (I want to write to a file for example on c:\myworkspace\filename.txt a string):
public void test_write_file(){
if(!solo.searchText("HOME")){
signIn("39777555333", VALID_PASSWORD);
}
try {
String content = "This is the content to write into file";
File file = new File("filename.txt");
// if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(content);
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
assertTrue(solo.searchText("HOME"));
}
This code should write to file on device; my goal is to write on a file on machine from which I'm launching the script; the application under test should have permission to write to memory card; but I ask how to go out from Android Environment and get my Desktop environment.
For tests I suppose you will need xml format to be saved: Create xml file and save it in internal storage android
And then you will need to copy saved file from your device, see this How to copy selected files from Android with adb pull
You could be not so lazy and search it yourself.
For reading from a file or writing to file you would have to use normal java method. There you can create a separate method to read/write, which can be called whenever needed. you can see examples here for normal text file and excel file.

Android Open and Save files to/from Google Drive SDK

I've spent the last six hours pouring over documents from Google and I still don't know how to get started with this. All I want to do is make it so my existing Android app can read files from Google Drive, upload new files to Google Drive, and edit existing files on Google Drive.
I've read that Drive SDK v2 was focused solely on making it easy for Android (and mobile in general) developers to use it, and yet there seems to be virtually nothing in their documentation about it.
Ideally, I'd like someone to point at some decent documentation, example, or tutorial covering how to do this (keep in mind I'm using Android. They have plenty of stuff on how to use Drive with the Google App Engine; I have already looked at it and I have no idea how to go from that to an Android app.)
I need to know which libraries I need to download and add to my project, what I need to add to my manifest, and how I can ultimately get a list of files from Google Drive, download one, and then upload a modified version.
Ideally, I'd like it to handle accounts automatically, the way that the officially Google Drive app does.
Edit: Claudio Cherubino says that Google Play Services is now available and will make this process a lot easier. However, there's no sample code available (yet, he says it's coming soon... they said Google Play Services was "coming soon" 4 months ago, so there's a good chance this answer will continue to be the only completely working example of accessing Google Drive from your Android application into 2013.)
Edit 2X: Looks like I was off by about a month when I said Google wouldn't have a working example until next year. The official guide from Google is over here:
https://developers.google.com/drive/quickstart-android
I haven't tested their methods yet, so it's possible that my solutions from September 2012 (below) are still the best:
Google Play Services is NOT REQUIRED for this. It's a pain in the butt, and I spent well over 50 hours (edit: 100+ hours) figuring it all out, but here's a lot of things that it'll help to know:
THE LIBRARIES
For Google's online services in general you'll need these libraries in your project: (Instructions and Download Link)
google-api-client-1.11.0-beta.jar
google-api-client-android-1.11.0-beta.jar
google-http-client-1.11.0-beta.jar
google-http-client-android-1.11.0-beta.jar
google-http-client-jackson-1.11.0-beta.jar
google-oauth-client-1.11.0-beta.jar
guava-11.0.1.jar
jackson-core-asl-1.9.9.jar
jsr305-1.3.9.jar
For Google Drive in particular you'll also need this:
google-api-services-drive-v2-rev9-1.8.0-beta.jar (Download Link)
SETTING UP THE CONSOLE
Next, go to Google Console. Make a new project. Under Services, you'll need to turn on two things: DRIVE API and DRIVE SDK! They are separate, one does not automatically turn the other on, and YOU MUST TURN BOTH ON! (Figuring this out wasted at least 20 hours of my time alone.)
Still on the console, go to API Access. Create a client, make it an Android app. Give it your bundle ID. I don't think the fingerprints thing is actually important, as I'm pretty sure I used the wrong one, but try to get that right anyways (Google provides instructions for it.)
It'll generate a Client ID. You're going to need that. Hold onto it.
Edit: I've been told that I'm mistaken and that you only need to turn on Drive API, Drive SDK doesn't need to be turned on at all, and that you just need to use the Simple API Key, not set up something for Android. I'm looking into that right now and will probably edit this answer in a few minutes if i figure it out...
THE ANDROID CODE - Set Up and Uploading
First, get an auth token:
AccountManager am = AccountManager.get(activity);
am.getAuthToken(am.getAccounts())[0],
"oauth2:" + DriveScopes.DRIVE,
new Bundle(),
true,
new OnTokenAcquired(),
null);
Next, OnTokenAcquired() needs to be set up something like this:
private class OnTokenAcquired implements AccountManagerCallback<Bundle> {
#Override
public void run(AccountManagerFuture<Bundle> result) {
try {
final String token = result.getResult().getString(AccountManager.KEY_AUTHTOKEN);
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
Drive.Builder b = new Drive.Builder(httpTransport, jsonFactory, null);
b.setJsonHttpRequestInitializer(new JsonHttpRequestInitializer() {
#Override
public void initialize(JSonHttpRequest request) throws IOException {
DriveRequest driveRequest = (DriveRequest) request;
driveRequest.setPrettyPrint(true);
driveRequest.setKey(CLIENT ID YOU GOT WHEN SETTING UP THE CONSOLE BEFORE YOU STARTED CODING)
driveRequest.setOauthToken(token);
}
});
final Drive drive = b.build();
final com.google.api.services.drive.model.File body = new com.google.api.services.drive.model.File();
body.setTitle("My Test File");
body.setDescription("A Test File");
body.setMimeType("text/plain");
final FileContent mediaContent = new FileContent("text/plain", an ordinary java.io.File you'd like to upload. Make it using a FileWriter or something, that's really outside the scope of this answer.)
new Thread(new Runnable() {
public void run() {
try {
com.google.api.services.drive.model.File file = drive.files().insert(body, mediaContent).execute();
alreadyTriedAgain = false; // Global boolean to make sure you don't repeatedly try too many times when the server is down or your code is faulty... they'll block requests until the next day if you make 10 bad requests, I found.
} catch (IOException e) {
if (!alreadyTriedAgain) {
alreadyTriedAgain = true;
AccountManager am = AccountManager.get(activity);
am.invalidateAuthToken(am.getAccounts()[0].type, null); // Requires the permissions MANAGE_ACCOUNTS & USE_CREDENTIALS in the Manifest
am.getAuthToken (same as before...)
} else {
// Give up. Crash or log an error or whatever you want.
}
}
}
}).start();
Intent launch = (Intent)result.getResult().get(AccountManager.KEY_INTENT);
if (launch != null) {
startActivityForResult(launch, 3025);
return; // Not sure why... I wrote it here for some reason. Might not actually be necessary.
}
} catch (OperationCanceledException e) {
// Handle it...
} catch (AuthenticatorException e) {
// Handle it...
} catch (IOException e) {
// Handle it...
}
}
}
THE ANDROID CODE - Downloading
private java.io.File downloadGFileToJFolder(Drive drive, String token, File gFile, java.io.File jFolder) throws IOException {
if (gFile.getDownloadUrl() != null && gFile.getDownloadUrl().length() > 0 ) {
if (jFolder == null) {
jFolder = Environment.getExternalStorageDirectory();
jFolder.mkdirs();
}
try {
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(gFile.getDownloadUrl());
get.setHeader("Authorization", "Bearer " + token);
HttpResponse response = client.execute(get);
InputStream inputStream = response.getEntity().getContent();
jFolder.mkdirs();
java.io.File jFile = new java.io.File(jFolder.getAbsolutePath() + "/" + getGFileName(gFile)); // getGFileName() is my own method... it just grabs originalFilename if it exists or title if it doesn't.
FileOutputStream fileStream = new FileOutputStream(jFile);
byte buffer[] = new byte[1024];
int length;
while ((length=inputStream.read(buffer))>0) {
fileStream.write(buffer, 0, length);
}
fileStream.close();
inputStream.close();
return jFile;
} catch (IOException e) {
// Handle IOExceptions here...
return null;
}
} else {
// Handle the case where the file on Google Drive has no length here.
return null;
}
}
One last thing... if that intent gets sent off, you'll need to handle when it returns with a result.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 3025) {
switch (resultCode) {
case RESULT_OK:
AccountManager am = AccountManager.get(activity);
am.getAuthToken(Same as the other two times... it should work this time though, because now the user is actually logged in.)
break;
case RESULT_CANCELED:
// This probably means the user refused to log in. Explain to them why they need to log in.
break;
default:
// This isn't expected... maybe just log whatever code was returned.
break;
}
} else {
// Your application has other intents that it fires off besides the one for Drive's log in if it ever reaches this spot. Handle it here however you'd like.
}
}
THE ANDROID CODE - Updating
Two quick notes on updating the last modified date of a file on Google Drive:
You must provide a fully initialized DateTime. If you do not, you'll get a response of "Bad Request" from Google Drive.
You must use both setModifiedDate() on the File from Google Drive and setSetModifiedDate(true) on the update request itself. (Fun name, huh? "setSet[...]", there's no way people could mistype that one...)
Here's some brief sample code showing how to do an update, including updating the file time:
public void updateGFileFromJFile(Drive drive, File gFile, java.io.File jFile) throws IOException {
FileContent gContent = new FileContent("text/csv", jFile);
gFile.setModifiedDate(new DateTime(false, jFile.lastModified(), 0));
gFile = drive.files().update(gFile.getId(), gFile, gContent).setSetModifiedDate(true).execute();
}
THE MANIFEST
You'll need the following permissions: GET_ACCOUNTS, USE_CREDENTIALS, MANAGE_ACCOUNTS, INTERNET, and there's a good chance you'll need WRITE_EXTERNAL_STORAGE as well, depending on where you'd like to store the local copies of your files.
YOUR BUILD TARGET
Right click your project, go into it's properties, and under Android change the build target to Google APIs if you must. If they aren't there, download them from the android download manager.
If you're testing on an emulator, make sure its target is Google APIs, not generic Android.
You'll need a Google Account set up on your test device. The code as written will automatically use the first Google Account it finds (that's what the [0] is.) IDK if you need to have downloaded the Google Drive app for this to have worked. I was using API Level 15, I don't know how far back this code will work.
THE REST
The above should get you started and hopefully you can figure your way out from there... honestly, this is just about as far as I've gotten so far. I hope this helps A LOT of people and saves them A LOT of time. I'm fairly certain I've just written the most comprehensive set up guide to setting up an Android app to use Google Drive. Shame on Google for spreading the necessary material across at least 6 different pages that don't link to each other at all.
It's 2015, things have changed!
Get the 'Drive API for Android' with gradle:
compile 'com.google.android.gms:play-services-drive:7.8.0'
There's some new doco (although still lackluster IMO):
https://developers.google.com/drive/web/quickstart/android
And for those about to go caving...the biggest problem I encountered thus far is that there is absolutely no way of distinguishing folders that have been permanently deleted from folders that are normal...you can find them, you can create folders and files within them, only writing to the file DriveContents will always fail.
Check this video from Google I/O to learn how to integrate your Android app with Drive:
http://www.youtube.com/watch?v=xRGyzqD-vRg
Please be aware that what you see in the video is based on Google Play Services:
https://developers.google.com/android/google-play-services/
Take a look at Google's DrEdit Example, which has a folder called android/. Copy it, follow the readme, and it should work (works for me on an Android emulator with KitKat).
.
P.S.
Sorry for reviving this, but the new Google Drive Android API doesn't support full Drive access, only drive.file and drive.appdata authorization scopes, so if you need full access you have to go back to the good 'ol Google API's Client for Java (which the DrEdit example uses).

Categories

Resources