How to use AWS S3 PersistableDownload on Android SDK - android

Has anyone been able to use PersistableDownload on AWS Android SDK? I've been trying to use it to resume downloads when the App crashes, but with no success so far. I don't think I'm getting the concept serialize/deserialize right. Here is the code I got so far:
AmazonS3Client s3Client = getAmazonS3Client(Regions.SA_EAST_1);
TransferManager tx = new TransferManager(s3Client);
String bucket = "MyBucket";
String key = "IMG_20140915_132548.jpg";
String[] parts = key.split("/");
String fileName = parts[parts.length - 1];
final String full_path = "/storage/sdcard0/" + fileName;
File file = new File(full_path);
FileInputStream fis = null;
if(file.exists()) {
try {
fis = new FileInputStream(file);
PersistableDownload persistableUpload = PersistableTransfer.deserializeFrom(fis);
Download meuDown = tx.resumeDownload(persistableUpload);
} catch (Exception e1) {
e1.printStackTrace();
}
}
else {
GetObjectRequest getRequest = new GetObjectRequest(bucket, "IMG_20140915_132548.jpg");
Download download = tx.download(getRequest, file, new S3ProgressListener() {
#Override
public void progressChanged(ProgressEvent arg0) {
long transferred = arg0.getBytesTransferred();
Log.d("AWS3", "" + transferred);
}
#Override
public void onPersistableTransfer(PersistableTransfer arg0) {
Log.d("AWS3", "Writing to file");
File f = new File("/storage/sdcard0/resume-upload");
FileOutputStream fos;
try {
if (f.exists() == false)
f.createNewFile();
fos = new FileOutputStream(f);
arg0.serialize(fos);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
I noticed that the onPersistableTransfer method is only called once, so I don't know how all the received bytes are serialized to the disk.
Any advices on how to get PersistableDownload to work? I'm using the SDK 2.1, with a real cell phone (Android 4.4.4) and Eclipse.

From the above code, I see that you are passing the partially downloaded image file to resume the download process.
if(file.exists()) {
try {
fis = new FileInputStream(file);
PersistableDownload persistableUpload = PersistableTransfer.deserializeFrom(fis);
Download meuDown = tx.resumeDownload(persistableUpload);
} catch (Exception e1) {
e1.printStackTrace();
}
}
Here file is referring to the partially downloaded image file. You will need to pass the file "/storage/sdcard0/resume-upload" to resume the upload.

Related

Getting error toast message on target application when using intent with action_view

I have webview which we have php application loaded. the application lists item which the user selects. when a list is selected. it does a redirect with a file path from the server which is captured using the below code.
1.get the file name and extension from the url and use it too create a new file which we will use it for writing outputstream to it.
2. call the downloadFile() method to read the file
3. call the ShoWeDrawings() passing the filename to use it to read the file and pass it to open it using intent action_view with another app.
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// This is my web site, so do not override; let my WebView load the page
if(url.contains("Files") ) {
String filename = url.substring(url.lastIndexOf('/') +1);
String extStorageDirectory = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) + "/EASM";
File folder = new File(extStorageDirectory);
if (!folder.exists()) {
folder.mkdir();
}
File file = new File(folder, filename);
try {
file.createNewFile();
} catch (IOException e1) {
e1.printStackTrace();
}
Downloader.DownloadFile( url,file);
ShoWeDrawings(filename);
return true;
}
return false;
}
download class
public class Downloader {
private static Context context;
// public Context context ;
public static void DownloadFile(String fileURL, File directory){
try{
FileOutputStream f = new FileOutputStream(directory);
URL u = new URL(fileURL);
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(false);
c.setConnectTimeout(10000);
c.setReadTimeout(10000);
c.connect();
int status = c.getResponseCode();
// InputStream in = c.getErrorStream();
InputStream in = c.getInputStream();
// c.getErrorStream();
byte[] buffer = new byte[4096];
int len1 = 0;
while ((len1 = in.read(buffer)) > 0) {
f.write(buffer, 0, len1);
}
f.close();
in.close();
// Toast.makeText(context.getApplicationContext(), "A new file is downloaded successfully", Toast.LENGTH_SHORT).show();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
ShoWeDrawings method
private void ShoWeDrawings(String filename) {
File file = new File( getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)+"/EASM/"+filename);
// Uri uri = Uri.fromFile(file);
try {
Intent mIntent = new Intent(Intent.ACTION_VIEW);
// mIntent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Uri.fromFile(file));
// mIntent.putExtra(Intent.EXTRA_STREAM,Uri.fromFile(file));
mIntent.setDataAndType(Uri.fromFile(file), "application/octet-stream");
mIntent.setPackage("com.solidworks.eDrawingsAndroid");
mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Intent.createChooser(mIntent, "Choose Application");
startActivity(mIntent);
}
catch (Exception e)
{
e.printStackTrace();
}
}
now the problem comes with the opening of the file using the targeted app. i get a toast error message. Im not sure if its due to permissions or its the app that has problems. By the way i have upgraded to android 11 and i cant even view data/ folder on the tablet. i can only see the files via pc. The error message that im getting is - filename:error copying file to documents folder see picture below.
I tried to change the code and restarting the tablet thinking it might have been the updates that i pushed.

Download file within the app by clicking on the weblink.

I am developing app like playstore in which user can download any app. i have many apps in my application that i got from my website through wp api v2. when we click on any of the available application detail opened and it have a download link. when we click on the link it goes to the browser but what i want is when we click on any of the apps downloading link downloading should start within my app with progress bar. i didn't found any appropriate solution yet on stack or anywhere.
Here is the screenshot attached for better understanding. arrow is pointing to the downloading link.
Try this code, you can put this on click of the link(textview)
private static void downloadFile(String url, File outputFile) {
try {
URL u = new URL(url);
URLConnection conn = u.openConnection();
int contentLength = conn.getContentLength();
DataInputStream stream = new DataInputStream(u.openStream());
byte[] buffer = new byte[contentLength];
stream.readFully(buffer);
stream.close();
DataOutputStream fos = new DataOutputStream(new FileOutputStream(outputFile));
fos.write(buffer);
fos.flush();
fos.close();
} catch(FileNotFoundException e) {
return; // swallow a 404
} catch (IOException e) {
return; // swallow a 404
}
}
you can use intent service to download the app.
Here is the code :
public class DownloadService extends IntentService {
File cacheDir;
public DownloadService() {
super("DownloadService");
}
#Override
public void onCreate() {
super.onCreate();
String tmpLocation =
Environment.getExternalStorageDirectory().getPath();
cacheDir = new File(tmpLocation);
if (!cacheDir.exists()) {
cacheDir.mkdirs();
}
}
#Override
protected void onHandleIntent(Intent intent) {
String remoteUrl = intent.getExtras().getString("url");
String location;
String filename =
remoteUrl.substring(
remoteUrl.lastIndexOf(File.separator) + 1);
File tmp = new File(cacheDir.getPath()
+ File.separator + filename);
if (tmp.exists()) {
location = tmp.getAbsolutePath();
stopSelf();
return;
}
try {
URL url = new URL(remoteUrl);
HttpURLConnection httpCon =
(HttpURLConnection) url.openConnection();
if (httpCon.getResponseCode() != 200)
throw new Exception("Failed to connect");
InputStream is = httpCon.getInputStream();
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int n = 0;
while (-1 != (n = is.read(buf))) {
out.write(buf, 0, n);
}
out.close();
is.close();
byte[] response = out.toByteArray();
FileOutputStream fos = new FileOutputStream(tmp);
fos.write(response);
fos.flush();
fos.close();
is.close();
location = tmp.getAbsolutePath();
} catch (Exception e) {
Log.e("Service", "Failed!", e);
}
}
}
Run this service with url passed in the intent

Able to Receive file but file not storing in Android External Storage

I am creating Xmpp application using SMACK api and Spark for test.
I am able to send from Spark but I cannot see Any Directory and File created in android gallery.
I log the method incoming.getAmountWritten() and it is giving me
07-27 21:00:58.789: V/Receiving Status ...(17652): 208861
It means I have got the file and now I have to write on physical storage. May be there is problem with my android code.
Please find Android Code
#Override
public void fileTransferRequest(final FileTransferRequest fileRequest) {
final File dir = Environment.getExternalStorageDirectory();
final File folder = new File(dir+ "/illuxplain/");
boolean success = true;
if (!folder.exists()) {
success = folder.mkdir();
}
if (success) {
Thread receiving = new Thread(new Runnable() {
#Override
public void run() {
IncomingFileTransfer incoming = fileRequest.accept();
Log.v("Receiving File Name", incoming.getFileName());
File file = new File(folder, incoming.getFileName());
try {
incoming.recieveFile(file);
while (!incoming.isDone()) {
try {
Thread.sleep(1000L);
} catch (Exception e) {
Log.e("", e.getMessage());
}
if (incoming.getStatus().equals(Status.error)) {
Log.e("ERROR!!! ", incoming.getError() + "");
}
if (incoming.getException() != null) {
incoming.getException().printStackTrace();
}
}
Log.v("Receiving Status ... ",""+incoming.getAmountWritten());
} catch (Exception e) {
e.printStackTrace();
Log.e("", e.getMessage());
}
}
});
receiving.start();
}else{
System.out.println("Directory Not Created");
}
}
}
When I go to gallery and see if I got the file. I see no directory created and of course no file.
You need to write the data into the file. Here is an example to code to write the data in to the file
File file = new File(folder, incoming.getFileName());
String string = "Hello world!";
FileOutputStream outputStream;
try {
outputStream = new FileOutputStream(file);
outputStream.write(string.getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}

Dowloading a text file from web

I want to download a text file from a web url and save it locally on the device and use it in my app.
Code:
try {
File file = new File(getFilesDir(), "file.txt");
if (file.length() > 0) {
//File already exists and it is not empty
return;
}
URL url = new URL("https://www.abc.com/file.txt");
FileOutputStream fos = new FileOutputStream(file);
InputStream in = url.openStream();
byte[] buffer = new byte[1024];
int length = 0;
while ((length = in.read(buffer)) > 0) {
fos.write(buffer, 0, length);
}
fos.flush();
fos.close();
} catch (Exception e) {
// TODO:
}
As you can see, the code goes with getFilesDir() assuming that always exists. However there are few questions, with proper network connection and permissions:
Does my assumption of getFilesDir() fail in any case?
Are there any cases of either file not downloaded/wrong content etc.., with this code?
Once I faced an issue where the file is downloaded but has all encoded characters, no matter how may times I downloaded it, it still had the same encoded text. Only when I re-installer my app, then the proper text was downloaded. And never got that issue ever since. Any reason for that weird behavior?
EDIT:
Here is what I get as the content when I try to read the file which I downloaded(happens sometimes, 1 in 10) shown in the logcat:
Code to read the file:
BufferedReader inputReader= = new BufferedReader(
new InputStreamReader(new FileInputStream(file)));
String inputString;
StringBuffer stringBuffer = new StringBuffer();
while ((inputString = inputReader.readLine()) != null) {
Log.e("inputString: ", inputString);
}
inputReader.close();
Thank You
Does my assumption of getFilesDir() fail in any case?
According to the documentation it should always work with no permissions required.
Are there any cases of either file not downloaded/wrong content etc..,
with this code?
Sure, I mean just a simple connection drop will cause download failure and so many other things can go wrong like missing required permission (android.permission.INTERNET), wrong encoding, disk full, ...
Once I faced an issue where the file is downloaded but has all encoded
characters, no matter how may times I downloaded it, it still had the
same encoded text. Only when I re-installer my app, then the proper
text was downloaded. And never got that issue ever since. Any reason
for that weird behavior?
It might have been an encoding issue, wrap your FileOutputStream in an OutputStreamWriter, which allows you to pass encoding parameter in the constructor.
Writer writer = new OutputStreamWriter(fos);
.
.
.
writer.write(buffer, 0, length);
The following example may be helpful:
try {
// Create a URL for the desired page
URL url = new URL("mysite.com/thefile.txt");
// 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)
}
in.close();
} catch (MalformedURLException e) {
} catch (IOException e) {
}
That's not really an answer but an advice, use ion a networking library for Android.
From examples:
Ion.with(context)
.load("http://example.com/really-big-file.zip")
// have a ProgressBar get updated automatically with the percent
.progressBar(progressBar)
// and a ProgressDialog
.progressDialog(progressDialog)
// can also use a custom callback
.progress(new ProgressCallback() {#Override
public void onProgress(int downloaded, int total) {
System.out.println("" + downloaded + " / " + total);
}
})
.write(new File("/sdcard/really-big-file.zip"))
.setCallback(new FutureCallback<File>() {
#Override
public void onCompleted(Exception e, File file) {
// download done...
// do stuff with the File or error
}
});
All operations are done not in the UI thread, so the user always see a responsive app.
Try with below code:
public void downloadFile(){
String DownloadUrl = "Paste Url to download a text file hereā€¦";
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(DownloadUrl));
request.setDescription("sample text file for testing"); //appears the same in Notification bar while downloading
request.setTitle("Sample.txt");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
}
request.setDestinationInExternalFilesDir(getApplicationContext(),null, "sample.pdf");
// get download service and enqueue file
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
}
public static boolean isDownloadManagerAvailable(Context context) {
try {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {
return false;
}
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setClassName("com.android.providers.downloads.ui","com.android.providers.downloads.ui.DownloadList");
List <resolveinfo> list = context.getPackageManager().queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
} catch (Exception e) {
return false;
}
}
I cannot really comment on what goes wrong in your case, I will post a snippet of a code I'm using to detect what type of file I'm targeting and then get it. This has always worked as expected for me. I've modified my "onPostExecute" method to suit my answer here and I've tried to keep the names of my variables similar to yours. I've omitted the download progress indication bar to simplify the snippet. The download has to be done in the background, therefore "AsyncTask" is used. For the snippet I use random text file from google.
final String file_url = "https://www.kernel.org/doc/Documentation/power/drivers-testing.txt";
String fileExtension = MimeTypeMap.getFileExtensionFromUrl(file_url);
final String fileName = URLUtil.guessFileName(file_url, null, fileExtension);
final String path = Environment.getExternalStorageDirectory().toString() + "/" + fileName;
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
try {
URL url = new URL(file_url);
URLConnection connection = url.openConnection();
connection.connect();
// download the file
InputStream in = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(path);
byte buffer[] = new byte[1024];
int length;
while ((length = in.read(buffer)) != -1) {
output.write(buffer, 0, length);
}
output.flush();
output.close();
in.close();
} catch (IOException e) {
Log.e("Downloading file", "Download Error", e);
}
return null;
}
#Override
public void onPostExecute(Void result) {
try {
File file = new File(path);
BufferedReader inputReader = new BufferedReader(new FileReader(file));
String inputString;
while ((inputString = inputReader.readLine()) != null) {
Log.e("inputString: ", inputString);
}
inputReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}.execute();

Storing serialized objects into sdcard as file causing FileNotFoundException

I want to serialize an object and store it inside sdcard under my project name but I'm getting FileNotFoundException.
My code is written below:
FileOutputStream fileOutputStream = null;
ObjectOutputStream objectOutputStream = null;
File dir = new File(Environment.getExternalStorageDirectory(), FILE_LOCATION + username);
try {
if(!dir.exists()) {
dir.mkdirs();
}
File file = new File(dir, FILE_NAME);
fileOutputStream = new FileOutputStream(file);
objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(formList);
objectOutputStream.close();
} catch(IOException ioException) {
ioException.getMessage();
} catch (Exception e) {
e.getMessage();
}
What is the reason for this issue? I'm running in emulator and my application is in android 3.0.
I suspect your filename is invalid, maybe that . in the directory? Or the file-name its self.
Correct me if I'm wrong, but don't you have to create the File before you write to it?
File file = new File(dir, FILE_NAME);
if (!file.exists()) {
file.createNewFile();
}
I would like to share my solution for this since I got a lot of help from Stackoverflow on this issue (by searching for previous answers). My solution resulted for a couple of hours of searching and piecing together solutions. I hope it helps someone.
This will write and read an ArrayList of custom objects to and from External Storage.
I have a class that provides IO to my activities and other classes. Alarm is my custom class.
#SuppressWarnings("unchecked")
public static ArrayList<Alarm> restoreAlarmsFromSDCard(String fileName,
Context context) {
FileInputStream fileInputStream = null;
ArrayList<Alarm> alarmList = new ArrayList<Alarm>();//Alarm is my custom class
//Check if External storage is mounted
if (Environment.getExternalStorageState() != null) {
File dir = new File(Environment.getExternalStorageDirectory(),
"YourAppName/DesiredDirectory");
try {
if (!dir.exists()) {
Log.v("FileIOService", "No Such Directory Exists");
}
File file = new File(dir, fileName);
fileInputStream = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fileInputStream);
alarmList = (ArrayList<Alarm>) ois.readObject();
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
} else {
//Do something here to warn user
}
return alarmList;
}
public static void saveAlarmsToSDCard(String fileName, ArrayList<Alarm> alarmList,Context context) {
FileOutputStream fileOutputStream = null;
ObjectOutputStream objectOutputStream = null;
if (Environment.getExternalStorageState() != null) {
File dir = new File(Environment.getExternalStorageDirectory(),
"YourAppName/DesiredDirectory");
try {
if (!dir.exists()) {
dir.mkdirs();
}
File file = new File(dir, fileName);
fileOutputStream = new FileOutputStream(file);
objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(alarmList);
objectOutputStream.close();
} catch (IOException ioException) {
ioException.getMessage();
} catch (Exception e) {
e.getMessage();
}
}else{
//Do something to warn user that operation did not succeed
}
}

Categories

Resources