Downloading an image into internal storage and reading it in android - java

I am trying to download an image from url and i want to display it in an imageview.My code is as follows:
package com.example.imageinternalstorage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends Activity {
Button btnstoreinternal,btnloadfrominternal;
ImageView iv_category;
boolean download_success;
String URL_image="http://footballultimate.com/storelocator/resource/uploads/";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnstoreinternal=(Button) findViewById(R.id.btnstoreinternal);
btnloadfrominternal=(Button) findViewById(R.id.btnloadfrominternal);
iv_category=(ImageView) findViewById(R.id.iv_category);
btnstoreinternal.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
download_success=downloadFile(URL_image+"Hospital.png");
if(download_success==true)
{
Toast.makeText(getApplicationContext(),"Download success",Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(getApplicationContext(),"Download failed",Toast.LENGTH_LONG).show();
}
}
});
btnloadfrominternal.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
iv_category.setImageBitmap(getImageBitmap(MainActivity.this,"Hospital.png"));
}
});
}
public boolean downloadFile(final String path)
{
try
{
URL url = new URL(path);
URLConnection ucon = url.openConnection();
ucon.setReadTimeout(5000);
ucon.setConnectTimeout(10000);
InputStream is = ucon.getInputStream();
BufferedInputStream inStream = new BufferedInputStream(is, 1024 * 5);
File file = new File(MainActivity.this.getDir("filesdir", Context.MODE_PRIVATE) + "/Hospital.png");
if (file.exists())
{
file.delete();
}
file.createNewFile();
FileOutputStream outStream = new FileOutputStream(file);
byte[] buff = new byte[5 * 1024];
int len;
while ((len = inStream.read(buff)) != -1)
{
outStream.write(buff, 0, len);
}
outStream.flush();
outStream.close();
inStream.close();
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
return true;
}
public Bitmap getImageBitmap(Context context,String name){
try{
FileInputStream fis = context.openFileInput(name);
Bitmap b = BitmapFactory.decodeStream(fis);
fis.close();
return b;
}
catch(Exception e){
}
return null;
}
}
When i click the first button the download is shown as successfull.But when i click the second button to display the image in the imageview nothing happens.So can anyone give me a replacement code for the retrival code from memory:
public Bitmap getImageBitmap(Context context,String name){
try{
FileInputStream fis = context.openFileInput(name);
Bitmap b = BitmapFactory.decodeStream(fis);
fis.close();
return b;
}
catch(Exception e){
}
return null;
}
The code for dowloading is:
public boolean downloadFile(final String path)
{
try
{
URL url = new URL(path);
URLConnection ucon = url.openConnection();
ucon.setReadTimeout(5000);
ucon.setConnectTimeout(10000);
InputStream is = ucon.getInputStream();
BufferedInputStream inStream = new BufferedInputStream(is, 1024 * 5);
File file = new File(MainActivity.this.getDir("filesdir", Context.MODE_PRIVATE) + "/Hospital.png");
if (file.exists())
{
file.delete();
}
file.createNewFile();
FileOutputStream outStream = new FileOutputStream(file);
byte[] buff = new byte[5 * 1024];
int len;
while ((len = inStream.read(buff)) != -1)
{
outStream.write(buff, 0, len);
}
outStream.flush();
outStream.close();
inStream.close();
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
return true;
}

Android does not allow such Network operations in the onCreate method ever since version >2.2 I think.
Solutions:
1- Try using a private class inside the main class that extends AsyncTask and if you are not sure about the return type you can use Void. E.g take a look at this AndroidHive tutorial ,while he is retrieving JSON data from a website he calls the 'GetContacts' class which he created to do the network operations.
2-If you are not feeling all this AsyncTask stuff take a look at Android Volley library which has a nice AndroidHive tutorial as well.

while downloading image you are storing it in "filesdir" while for retrieving image you are using openFileInput(name)
replace FileInputStream fis = context.openFileInput(name); By File file = new File("filesdir", FILENAME);
else use this for storing downloaded image
String path=context.getFilesDir().getAbsolutePath();
File file = new File(path + File.separator + fileName);
and this for retriving image
File myFile = new File ( path+ File.separator + fileName);
byte [] mybytearray = new byte [(int)myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);

Related

Starting new Activity after finish of several Async-Tasks

I tried to Download and Unzip files if there is an update on a server and all works perfect. But I want to open the next Activity only after all files have been downloaded and unzipped, not when it started downloading.
This is my Activity:
package com.example;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.PowerManager;
import android.os.StrictMode;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.WindowManager;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
public class Update extends AppCompatActivity {
private ProgressDialog ringProgressDialog;
private static Boolean finished = false;
private String read(String fileName) {
StringBuilder retString = new StringBuilder();
String zeilenumbruch = "\n";
BufferedReader reader = null;
try {
File file = new File(fileName);
FileInputStream in = new FileInputStream(Environment.getExternalStorageDirectory().toString() + "/.example/Anleitungen/.data/Versions/" + fileName);
reader = new BufferedReader(new InputStreamReader(in));
String zeile;
while ((zeile = reader.readLine()) != null) {
retString.append(zeile);
}
reader.close();
} catch (IOException ex) {
Log.e(getPackageName(), ex.getMessage());
}
return retString.toString();
}
public static String getTextOfUrl(String uri) throws Exception {
StringBuilder result = new StringBuilder();
URL url = new URL(uri);
String line = null;
BufferedReader reader = null;
finished = false;
try {
reader = new BufferedReader(new InputStreamReader(url.openStream()));
while ((line = reader.readLine()) != null) {
result.append(line);
}
return result.toString();
} finally {
if (reader != null) {
reader.close();
}
finished = true;
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_update);
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
final PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "Updating");
wl.acquire();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
AsyncTaskRunner runner = new AsyncTaskRunner();
runner.execute();
}
private void downloadAndUnzipContent(String path, String urlPath) {
String url = urlPath;
DownloadFileAsync download = new DownloadFileAsync(path, this, new DownloadFileAsync.PostDownload() {
#Override
public void downloadDone(File file) {
Log.i(getPackageName(), "file download completed");
// check unzip file now
Decompress unzip = new Decompress(Update.this, file, true);
unzip.unzip();
Log.i(getPackageName(), "File unzip completed");
}
});
download.execute(url);
}
private void downloadContent(String path, String urlPath) {
DownloadFileAsync download = new DownloadFileAsync(path, this, new DownloadFileAsync.PostDownload() {
#Override
public void downloadDone(File file) {
Log.i(getPackageName(), "file download completed");
}
});
download.execute(urlPath);
}
private class AsyncTaskRunner extends AsyncTask<String, String, String> {
private String resp;
#Override
protected String doInBackground(String... params) {
try {
List<String> files = new ArrayList<String>();
files.add("Archiv");
files.add("Funkempfaenger");
files.add("Funkhandsender");
files.add("Funksender");
files.add("Funksensoren");
files.add("Hausautomatisierung");
files.add("Jalousieantriebe");
files.add("Rohrantriebe");
files.add("SensorenKabelgebunden");
files.add("Sonderantriebe");
files.add("Torantriebe");
files.add("Torsteuerungen");
files.add("WandgeraeteKabelgebunden");
for (int uI = 0; uI < files.size(); uI++) {
try {
String newVersion = getTextOfUrl("http://www.example.com/zip/Versions/" + files.get(uI) + ".txt");
int nV = Integer.parseInt(newVersion);
String readString = files.get(uI) + ".txt";
String oldVersion = read(readString);
int iV = Integer.parseInt(oldVersion);
if (iV < nV) {
while (!finished) {
Log.i(getPackageName(), "Finished = False");
}
String dlPath = Environment.getExternalStorageDirectory() + "/.example/Anleitungen/.data/" + files.get(uI) + ".zip";
String dlPath2 = Environment.getExternalStorageDirectory() + "/.example/Anleitungen/.data/Versions/" + files.get(uI) + ".txt";
downloadAndUnzipContent(dlPath, "http://www.example.com/zip/Versions/" + files.get(uI) + ".zip");
downloadContent(dlPath2, "http://www.example.com/zip/Versions/" + files.get(uI) + ".txt");
}
} catch (Exception e) {
e.printStackTrace();
publishProgress(e.toString());
}
}
} catch (Exception e) {
e.printStackTrace();
}
return "HI!";
}
/*
* (non-Javadoc)
*
* #see android.os.AsyncTask#onPostExecute(java.lang.Object)
*/
#Override
protected void onPostExecute(String result) {
// execution of result of Long time consuming operation
Toast.makeText(Update.this, getString(R.string.UpdateFinished), Toast.LENGTH_LONG).show();
Intent intent = new Intent(Update.this, Home.class);
startActivity(intent);
finish();
}
/*
* (non-Javadoc)
*
* #see android.os.AsyncTask#onPreExecute()
*/
#Override
protected void onPreExecute() {
}
/*
* (non-Javadoc)
*
* #see android.os.AsyncTask#onProgressUpdate(Progress[])
*/
#Override
protected void onProgressUpdate(String... text) {
Toast.makeText(Update.this, text[0], Toast.LENGTH_SHORT).show();
}
}
#Override
public void onBackPressed() {
Log.i(getPackageName(), "Back pressed");
}
}
This is my Decompress.class:
package com.example;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class Decompress {
private File _zipFile;
private InputStream _zipFileStream;
private Context context;
private static String ROOT_LOCATION = "/sdcard";
private static final String TAG = "UNZIPUTIL";
private Boolean pathNew;
public Decompress(Context context, File zipFile, Boolean path) {
_zipFile = zipFile;
this.context = context;
pathNew = path;
if (pathNew) {
ROOT_LOCATION = "/sdcard/.example/Anleitungen";
}
_dirChecker("");
}
public Decompress(Context context, InputStream zipFile) {
_zipFileStream = zipFile;
this.context = context;
_dirChecker("");
}
public void unzip() {
try {
Log.i(TAG, "Starting to unzip");
InputStream fin = _zipFileStream;
if(fin == null) {
fin = new FileInputStream(_zipFile);
}
ZipInputStream zin = new ZipInputStream(fin);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
Log.v(TAG, "Unzipping " + ze.getName());
if(ze.isDirectory()) {
_dirChecker(ROOT_LOCATION + "/" + ze.getName());
} else {
FileOutputStream fout = new FileOutputStream(new File(ROOT_LOCATION, ze.getName()));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int count;
// reading and writing
while((count = zin.read(buffer)) != -1)
{
baos.write(buffer, 0, count);
byte[] bytes = baos.toByteArray();
fout.write(bytes);
baos.reset();
}
fout.close();
zin.closeEntry();
}
}
zin.close();
Log.i(TAG, "Finished unzip");
} catch(Exception e) {
Log.e(TAG, "Unzip Error", e);
Toast.makeText(context, "Error while unzipping: " + e.toString(), Toast.LENGTH_LONG).show();
}
}
private void _dirChecker(String dir) {
File f = new File(dir);
Log.i(TAG, "creating dir " + dir);
if(dir.length() >= 0 && !f.isDirectory() ) {
f.mkdirs();
}
}
}
This is my DownloadFileAsnyc.class:
package com.example;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
public class DownloadFileAsync extends AsyncTask<String, String, String> {
private static final String TAG ="DOWNLOADFILE";
public static final int DIALOG_DOWNLOAD_PROGRESS = 0;
private PostDownload callback;
private Context context;
private FileDescriptor fd;
private File file;
private String downloadLocation;
public DownloadFileAsync(String downloadLocation, Context context, PostDownload callback){
this.context = context;
this.callback = callback;
this.downloadLocation = downloadLocation;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... aurl) {
int count;
try {
URL url = new URL(aurl[0]);
URLConnection connection = url.openConnection();
connection.connect();
int lenghtOfFile = connection.getContentLength();
Log.d(TAG, "Length of the file: " + lenghtOfFile);
InputStream input = new BufferedInputStream(url.openStream());
file = new File(downloadLocation);
FileOutputStream output = new FileOutputStream(file); //context.openFileOutput("content.zip", Context.MODE_PRIVATE);
Log.d(TAG, "file saved at " + file.getAbsolutePath());
fd = output.getFD();
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress(""+(int)((total*100)/lenghtOfFile));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {}
return null;
}
protected void onProgressUpdate(String... progress) {
//Log.d(TAG,progress[0]);
}
#Override
protected void onPostExecute(String unused) {
if(callback != null) callback.downloadDone(file);
}
public static interface PostDownload{
void downloadDone(File fd);
}
}
Please help me. Sorry for my bad English.
Thank you.
You are starting the new Activity whenever AsyncTaskRunner finishes executing its background job. AsyncTaskRunner is basically just launching multiple DownloadFileAsync tasks.
AsyncTaskRunner won't wait for the launched tasks to complete. It will just launch them and finish the task which causes your new Activity to start.
The optimal way to fix this is to use only one AsyncTask that process each file sequentially. A dirty way would be to make AsyncTaskRunner wait for each DownloadFileAsync task to finish before launching the next. You can do this by calling the .get() method on each task:
download.execute(url).get();
But again, this defeats the purpose of AsyncTasks.

Read a pdf file from assets folder

public void DOCS(View btnDocs)
{
File fileBrochure = new File("android.resource://com.project.datastructure/assets/abc.pdf");
if (!fileBrochure.exists())
{
CopyAssetsbrochure();
}
/** PDF reader code */
File file = new File("android.resource://com.project.datastructure/assets/abc.pdf");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file),"application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try
{
getApplicationContext().startActivity(intent);
}
catch (ActivityNotFoundException e)
{
Toast.makeText(Stack_dr.this, "NO Pdf Viewer", Toast.LENGTH_SHORT).show();
}
}
private void CopyAssetsbrochure() {
AssetManager assetManager = getAssets();
String[] files = null;
try
{
files = assetManager.list("");
}
catch (IOException e){}
for(int i=0; i<files.length; i++)
{
String fStr = files[i];
if(fStr.equalsIgnoreCase("abc.pdf"))
{
InputStream in = null;
OutputStream out = null;
try
{
in = assetManager.open(files[i]);
out = new FileOutputStream("/sdcard/" + files[i]);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
break;
}
catch(Exception e){}
}
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException
{
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
I am trying to read a pdf file from assets folder which is present in my application folder . Everything is working perfectly when i click on my DOCS button a pop up comes to let me choose an application for opening the pdf i.e "abc.pdf" but after selecting an option i get an error message "The file path is not valid". I think their is some problem with the path which i have specified in the code.
please help
Try this
public class SampleActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
CopyReadAssets();
}
private void CopyReadAssets()
{
AssetManager assetManager = getAssets();
InputStream in = null;
OutputStream out = null;
File file = new File(getFilesDir(), "abc.pdf");
try
{
in = assetManager.open("abc.pdf");
out = openFileOutput(file.getName(), Context.MODE_WORLD_READABLE);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch (Exception e)
{
Log.e("tag", e.getMessage());
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(
Uri.parse("file://" + getFilesDir() + "/abc.pdf"),
"application/pdf");
startActivity(intent);
}
private void copyFile(InputStream in, OutputStream out) throws IOException
{
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1)
{
out.write(buffer, 0, read);
}
}
}
Make sure to include
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
in manifest
You can do it like this (tested and working on API 27)
Step 1
Add following dependency in your app gradle:
implementation 'com.github.barteksc:android-pdf-viewer:2.8.2'
Step 2
Add following XML code:
<com.github.barteksc.pdfviewer.PDFView
android:id="#+id/pdfv"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.github.barteksc.pdfviewer.PDFView>
Step 3
Add following code in your java file:
public class MainActivity extends AppCompatActivity {
PDFView pdfView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pdfView=findViewById(R.id.pdfv);
pdfView.fromAsset("filename.pdf").load();
}
}
These changes will load a PDF file on creation of your activity.
Though this has been answered, I wanted to share my solution as I think it is a bit easier to include.
Usage:
new OpenLocalPDF(context, 'nameOfPDFStoredInAssets').execute()
And here is the OpenLocalPDF class:
public class OpenLocalPDF {
private static String TAG = OpenLocalPDF.class.getSimpleName();
private WeakReference<Context> contextWeakReference;
private String fileName;
public OpenLocalPDF(Context context, String fileName) {
this.contextWeakReference = new WeakReference<>(context);
this.fileName = fileName.endsWith("pdf") ? fileName : fileName + ".pdf";
}
public void execute() {
Context context = contextWeakReference.get();
if (context != null) {
new CopyFileAsyncTask().execute();
}
}
private class CopyFileAsyncTask extends AsyncTask<Void, Void, File> {
final String appDirectoryName = BuildConfig.APPLICATION_ID;
final File fileRoot = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOCUMENTS), appDirectoryName);
#Override
protected File doInBackground(Void... params) {
Context context = contextWeakReference.get();
AssetManager assetManager = context.getAssets();
File file = new File(fileRoot, fileName);
InputStream in = null;
OutputStream out = null;
try {
file.mkdirs();
if (file.exists()) {
file.delete();
}
file.createNewFile();
in = assetManager.open(fileName);
Log.d(TAG, "In");
out = new FileOutputStream(file);
Log.d(TAG, "Out");
Log.d(TAG, "Copy file");
copyFile(in, out);
Log.d(TAG, "Close");
in.close();
out.flush();
out.close();
return file;
} catch (Exception e)
{
Log.e(TAG, e.getMessage());
}
return null;
}
private void copyFile(InputStream in, OutputStream out) throws IOException
{
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1)
{
out.write(buffer, 0, read);
}
}
#Override
protected void onPostExecute(File file) {
super.onPostExecute(file);
Context context = contextWeakReference.get();
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(
Uri.fromFile(file),
"application/pdf");
context.startActivity(intent);
}
}
}
add this permission in Manifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
like say sunsil, but in the case for external directory.
import android.app.Activity;
import android.content.Intent;
import android.content.res.AssetManager;
import android.net.Uri;
import android.os.Environment;
import android.os.Bundle;
import android.util.Log;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
copyReadAssets();
}
private void copyReadAssets()
{
AssetManager assetManager = getAssets();
InputStream in = null;
OutputStream out = null;
String strDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+ File.separator + "Pdfs";
File fileDir = new File(strDir);
fileDir.mkdirs(); // crear la ruta si no existe
File file = new File(fileDir, "example2.pdf");
try
{
in = assetManager.open("example.pdf"); //leer el archivo de assets
out = new BufferedOutputStream(new FileOutputStream(file)); //crear el archivo
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch (Exception e)
{
Log.e("tag", e.getMessage());
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file://" + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + File.separator + "Pdfs" + "/example2.pdf"), "application/pdf");
startActivity(intent);
}
private void copyFile(InputStream in, OutputStream out) throws IOException
{
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1)
{
out.write(buffer, 0, read);
}
}
}
change parts of code like these:
out = new BufferedOutputStream(new FileOutputStream(file));
the before example is for Pdfs, in case of to example .txt
FileOutputStream fos = new FileOutputStream(file);
This works for me.
Step 1: In MainActivity.java
public class SampleActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//call this method by passing file name in params.
readFromAssets("User guide.pdf");
}
public static void readFromAssets(String fileName) {
AssetManager assetManager = getAssets();
InputStream in = null;
OutputStream out = null;
File file = new File(mContext.getFilesDir(), fileName);
try {
in = assetManager.open(fileName);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
out = mContext.openFileOutput(file.getName(), Context.MODE_PRIVATE);
} else {
out = mContext.openFileOutput(file.getName(), Context.MODE_WORLD_READABLE);
}
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch (Exception e) {
Log.e("tag", e.getMessage());
}
Uri pdfFileURI;
Intent intent = new Intent(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
pdfFileURI = FileProvider.getUriForFile(mContext,
BuildConfig.APPLICATION_ID + ".provider", file);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
pdfFileURI = Uri.parse("file://" + mContext.getFilesDir() + "/" + fileName);
}
intent.setDataAndType(pdfFileURI, "application/pdf");
mContext.startActivity(intent);
}
private static void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}
}
Step 2: Create provider_paths.xml inside res->xml->provider_paths.xml. See here
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external"
path="." />
<root-path
name="root"
path="." />
</paths>
Step 3: In AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppThemeMaterial">
<!-- INSIDE APPLICATION TAG -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
</application>
No answer worked for me out-of-the-box when attempting to open a file via an intent (in my case PDF) from the assets folder. So here is my solution combining 2 brilliant answers I'm sure it will help someone. Must be for api >= 24.
Once you have followed this link and added the your own GenericFileProvider and declared it in your manifest within the Application tag and created the provider_paths.xml simply use the below class and call it like:
OpenLocalPDF(this, "YOUR_PDF_NAME_IN_ASSETS_FOLDER.pdf").execute()
OpenLocalPdf.kt: (kudos too the OP https://stackoverflow.com/a/41212708/1133011)
import android.content.Context
import android.content.Intent
import android.content.res.AssetManager
import android.os.AsyncTask
import android.util.Log
import androidx.core.content.FileProvider
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
import java.io.OutputStream
import java.lang.ref.WeakReference
class OpenLocalPDF(context: Context?, fileName: String?) {
private val contextWeakReference: WeakReference<Context?>?
private val fileName: String?
fun execute() {
val context: Context = contextWeakReference!!.get()!!
if (context != null) {
CopyFileAsyncTask().execute()
}
}
private inner class CopyFileAsyncTask :
AsyncTask<Void?, Void?, File?>() {
val appDirectoryName: String? = co.za.umbiflow.BuildConfig.APPLICATION_ID
val fileRoot: File? = File(
android.os.Environment.getExternalStoragePublicDirectory(
android.os.Environment.DIRECTORY_DOCUMENTS
), appDirectoryName
)
override fun doInBackground(vararg params: Void?): File? {
val context: Context = contextWeakReference!!.get()!!
val assetManager: AssetManager = context.getAssets()
val file = File(fileRoot, fileName)
var `in`: InputStream? = null
var out: OutputStream? = null
try {
file.mkdirs()
if (file.exists()) {
file.delete()
}
file.createNewFile()
`in` = assetManager.open(fileName)
out = FileOutputStream(file)
copyFile(`in`, out)
`in`.close()
out.flush()
out.close()
return file
} catch (e: Exception) {
Log.e(TAG, e.message)
}
return null
}
private fun copyFile(`in`: InputStream, out: OutputStream) {
val buffer = ByteArray(1024)
var read: Int
while (`in`.read(buffer).also { read = it } != -1) {
out.write(buffer, 0, read)
}
}
override fun onPostExecute(file: File?) {
super.onPostExecute(file)
val context: Context = contextWeakReference!!.get()!!
var pdfUri =
FileProvider.getUriForFile(
context,
context.packageName + ".provider",
file!!
)
val intent = Intent()
intent.action = Intent.ACTION_VIEW
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.setDataAndType(
pdfUri,
"application/pdf"
)
context.startActivity(intent)
}
}
companion object {
private val TAG = OpenLocalPDF::class.java.simpleName
}
init {
contextWeakReference = WeakReference(context)
this.fileName = if (fileName!!.endsWith("pdf")) fileName else "$fileName.pdf"
}
}
This is a way to open multiple PDF files from assets using a zip file.
Step1: Copy a zip file(pdf.zip) into assets folder that contains the list of pdfs
Step2: Write PDF's into external cache inside the app in a Utils class
public static void writePDFs(Context context) {
try {
InputStream inputStream = context.getApplicationContext().getAssets().open("pdf.zip");
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
ZipEntry zipEntry;
File file = new File(context.getExternalCacheDir().getAbsolutePath(), "PDFs");
if (!file.getAbsoluteFile().exists()) {
if (file.mkdir()) {
BufferedOutputStream outputStream;
byte[] buffer = new byte[1024];
int count;
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
String s1 = file + "/" + zipEntry.getName();
File file1 = new File(s1);
if (!file1.exists()) {
file1.createNewFile();
}
outputStream = new BufferedOutputStream(new FileOutputStream(file1));
while ((count = zipInputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, count);
}
outputStream.flush();
outputStream.close();
zipInputStream.closeEntry();
}
}
zipInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Step3: Call the above function in Activities onCreate
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FileUtils.writePDFs(this);
}
Step4: Create a common function in Utils class to open the PDF
public static void openPDF(Activity activity, String fileName) {
if (activity == null) return;
File file = new File(activity.getExternalCacheDir().getAbsolutePath() + "/PDFs" + "/" + fileName);
Uri docUri = GenericFileProvider.getUriForFile(activity, activity.getApplicationContext().getPackageName(), file);
try {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(docUri, "application/pdf");
} else {
intent.setDataAndType(Uri.fromFile(file), "application/pdf");
}
activity.startActivityForResult(intent, ACTIVITY_VIEW_ATTACHMENT);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
}
}
Step5: Call the openPDF function on click on the view in Activity
myView.setOnClickListener(v -> ApplicationUtils.openPDF(this, "MyPdfFile.pdf"));
I had success, using the answer from cYrixmorten, with the OpenLocalPDF class.
But, Environment.DIRECTORY_DOCUMENTS is not supported for Android 18. To support Android 18 - 28, I had to make the following changes.
In "CopyFileAsyncTask", change the fileRoot declaration:
final File fileRoot = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOCUMENTS), appDirectoryName);
To this:
final File fileRoot = new File(Environment.getExternalStorageDirectory() + "/YourAppName");
In "onPostExecute", change this:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(
Uri.fromFile(file),
"application/pdf");
context.startActivity(intent);
To this:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(FileProvider.getUriForFile(context, "com.example.yourappname.provider", file), "application/pdf");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(intent);
Finally, setup your manifest to support the FileProvider as described in this post.
try this:
public String getAssetsPdfPath(Context context) {
String filePath = context.getFilesDir() + File.separator + "myFile.pdf";
File destinationFile = new File(filePath);
try {
FileOutputStream outputStream = new FileOutputStream(destinationFile);
InputStream inputStream = context.getAssets().open("myFile.pdf");
byte[] buffer = new byte[1024];
int length = 0;
while ((length = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, length);
}
outputStream.close();
inputStream.close();
} catch (IOException e) {
Log.e(context.getClass().getSimpleName(), "Error.");
}
return destinationFile.getPath();
}
If you want to open a .pdf file that is stored locally in the assets folder without using an Intent to launch an external app, I suggest using the Android class PdfRenderer. Documentation found here.
This is a good example that worked for me.
However, this example wouldn't run when I downloaded it. I had to change it a bit to use the copyReadAssets() function as mentioned in the other answers here, then to reference the file (after it has been copied) I use:
File file = new File("/data/data/" + getContext().getPackageName() + "/files/mypdf.pdf");
I also ended up modifying onAttach() because it was using the deprecated form of onAttach() and closeRenderer() because it was throwing errors for closing objects that were null.
So my complete PdfRendererBasicFragment.java file looks like this:
package com.example.android.pdfrendererbasic;
import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.pdf.PdfRenderer;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* This fragment has a big {#ImageView} that shows PDF pages, and 2 {#link android.widget.Button}s to move between
* pages. We use a {#link android.graphics.pdf.PdfRenderer} to render PDF pages as {#link android.graphics.Bitmap}s.
*/
public class PdfRendererBasicFragment extends Fragment implements View.OnClickListener {
/**
* Key string for saving the state of current page index.
*/
private static final String STATE_CURRENT_PAGE_INDEX = "current_page_index";
/**
* File descriptor of the PDF.
*/
private ParcelFileDescriptor mFileDescriptor;
/**
* {#link android.graphics.pdf.PdfRenderer} to render the PDF.
*/
private PdfRenderer mPdfRenderer;
/**
* Page that is currently shown on the screen.
*/
private PdfRenderer.Page mCurrentPage;
/**
* {#link android.widget.ImageView} that shows a PDF page as a {#link android.graphics.Bitmap}
*/
private ImageView mImageView;
/**
* {#link android.widget.Button} to move to the previous page.
*/
private Button mButtonPrevious;
/**
* {#link android.widget.Button} to move to the next page.
*/
private Button mButtonNext;
public PdfRendererBasicFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_pdf_renderer_basic, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Retain view references.
mImageView = (ImageView) view.findViewById(R.id.image);
mButtonPrevious = (Button) view.findViewById(R.id.previous);
mButtonNext = (Button) view.findViewById(R.id.next);
// Bind events.
mButtonPrevious.setOnClickListener(this);
mButtonNext.setOnClickListener(this);
// Show the first page by default.
int index = 0;
// If there is a savedInstanceState (screen orientations, etc.), we restore the page index.
if (null != savedInstanceState) {
index = savedInstanceState.getInt(STATE_CURRENT_PAGE_INDEX, 0);
}
showPage(index);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
openRenderer(context);
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(context, "Error! " + e.getMessage(), Toast.LENGTH_SHORT).show();
getActivity().finish();
}
}
#Override
public void onDetach() {
try {
closeRenderer();
} catch (IOException e) {
e.printStackTrace();
}
super.onDetach();
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (null != mCurrentPage) {
outState.putInt(STATE_CURRENT_PAGE_INDEX, mCurrentPage.getIndex());
}
}
/**
* Sets up a {#link android.graphics.pdf.PdfRenderer} and related resources.
*/
private void openRenderer(Context context) throws IOException {
// Copy the pdf to a usable location
CopyReadAssets();
File file = new File("/data/data/" + context.getPackageName() + "/files/sample.pdf");
mPdfRenderer = new PdfRenderer(ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY));
}
/**
* Closes the {#link android.graphics.pdf.PdfRenderer} and related resources.
*
* #throws java.io.IOException When the PDF file cannot be closed.
*/
private void closeRenderer() throws IOException {
if (mCurrentPage != null) {
mCurrentPage.close();
}
if (mPdfRenderer != null) {
mPdfRenderer.close();
}
if (mFileDescriptor != null) {
mFileDescriptor.close();
}
}
/**
* Shows the specified page of PDF to the screen.
*
* #param index The page index.
*/
private void showPage(int index) {
if (mPdfRenderer.getPageCount() <= index) {
return;
}
// Make sure to close the current page before opening another one.
if (null != mCurrentPage) {
mCurrentPage.close();
}
// Use `openPage` to open a specific page in PDF.
mCurrentPage = mPdfRenderer.openPage(index);
// Important: the destination bitmap must be ARGB (not RGB).
Bitmap bitmap = Bitmap.createBitmap(mCurrentPage.getWidth(), mCurrentPage.getHeight(),
Bitmap.Config.ARGB_8888);
// Here, we render the page onto the Bitmap.
// To render a portion of the page, use the second and third parameter. Pass nulls to get
// the default result.
// Pass either RENDER_MODE_FOR_DISPLAY or RENDER_MODE_FOR_PRINT for the last parameter.
mCurrentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
// We are ready to show the Bitmap to user.
mImageView.setImageBitmap(bitmap);
updateUi();
}
/**
* Updates the state of 2 control buttons in response to the current page index.
*/
private void updateUi() {
int index = mCurrentPage.getIndex();
int pageCount = mPdfRenderer.getPageCount();
mButtonPrevious.setEnabled(0 != index);
mButtonNext.setEnabled(index + 1 < pageCount);
getActivity().setTitle(getString(R.string.app_name_with_index, index + 1, pageCount));
}
/**
* Gets the number of pages in the PDF. This method is marked as public for testing.
*
* #return The number of pages.
*/
public int getPageCount() {
return mPdfRenderer.getPageCount();
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.previous: {
// Move to the previous page
showPage(mCurrentPage.getIndex() - 1);
break;
}
case R.id.next: {
// Move to the next page
showPage(mCurrentPage.getIndex() + 1);
break;
}
}
}
private void CopyReadAssets()
{
AssetManager assetManager = getActivity().getAssets();
InputStream in = null;
OutputStream out = null;
File file = new File(getActivity().getFilesDir(), "sample.pdf");
if(!file.exists()) {
try {
in = assetManager.open("sample.pdf");
out = getActivity().openFileOutput(file.getName(), Context.MODE_WORLD_READABLE);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch (Exception e) {
Log.e("tag", e.getMessage());
}
}
else {
Log.d("test", "file already exists");
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException
{
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1)
{
out.write(buffer, 0, read);
}
}
}
This code work on every android version:
Activity:
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.net.Uri;
import android.os.Environment;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.util.Log;
import android.widget.Toast;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import unimedbh.UnimedBH.R;
public class MainActivity extends Activity {
private static final int MY_PERMISSION_REQUEST_STORAGE = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSION_REQUEST_STORAGE);
} else {
copyReadAssets("YOUR_PDF_NAME.pdf");
}
}
private void copyReadAssets(String fileName) {
String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyFiles";
File dir = new File(dirPath);
if (!dir.exists()) {
dir.mkdirs();
}
AssetManager assetManager = getAssets();
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(fileName);
File outFile = new File(dirPath, fileName);
out = new FileOutputStream(outFile);
copyFile(in, out);
Intent intent = new Intent(Intent.ACTION_VIEW, FileProvider.getUriForFile(this, "com.package.name.fileprovider", outFile));
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(this, "Error!", Toast.LENGTH_SHORT).show();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}
}
Manifest.xml:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.package.name.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
file_paths.xml:
<paths>
<files-path name="app_directory" path="directory/"/>
</paths>
Tested in API 16-28, worked on all apiĀ“s!

downloading file in sdcard showing size 0

I have following code for downloading file from url to sdcard . This code is working fine for small file , but when the file size is large i am getting the downloaded file size 0.
Any help would be appreciated.
Java Code
setContentView(R.layout.activity_download_file);
String exStorageDirectory = Environment.getExternalStorageDirectory()
.toString();
File folder = new File(exStorageDirectory, "Folder");
folder.mkdir();
File file = new File(folder, "scjp.pdf");
try {
if (!file.exists()) {
file.createNewFile();
}
} catch (IOException e) {
e.printStackTrace();
}
downloadFile(
"http://java.net/downloads/jfjug/SCJP%20Sun%20Certified%20Programmer%20for%20Java%206-0071591060.pdf",
file);
}
private void downloadFile(String fileUrl, File directory) {
try {
FileOutputStream fileOutput = new FileOutputStream(directory);
URL url = new URL(fileUrl);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.connect();
InputStream inputStream = connection.getInputStream();
byte buffer[] = new byte[1024];
int len = 0;
while ((len = inputStream.read(buffer)) > 0) {
fileOutput.write(buffer, 0, len);
}
fileOutput.close();
Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Have a try with this code.
package com.example.stack;
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.RelativeLayout;
public class MainActivity extends Activity {
ProgressDialog mProgressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
overridePendingTransition(R.anim.enter, R.anim.enter);
setContentView(R.layout.activity_main);
// declare the dialog as a member field of your activity
// instantiate it within the onCreate method
mProgressDialog = new ProgressDialog(MainActivity.this);
mProgressDialog.setMessage("A message");
mProgressDialog.setIndeterminate(false);
mProgressDialog.setMax(100);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
// execute this when the downloader must be fired
DownloadFile downloadFile = new DownloadFile();
downloadFile.execute("http://java.net/downloads/jfjug/SCJP%20Sun%20Certified%20Programmer%20for%20Java%206-0071591060.pdf");
}
//The AsyncTask will look like this:
// usually, subclasses of AsyncTask are declared inside the activity class.
// that way, you can easily modify the UI thread from here
private class DownloadFile extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... sUrl) {
try {
URL url = new URL(sUrl[0]);
URLConnection connection = url.openConnection();
connection.connect();
// this will be useful so that you can show a typical 0-100% progress bar
int fileLength = connection.getContentLength();
// download the file
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream("/sdcard/output.pdf");
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
}
return null;
}
//The method above (doInBackground) runs always on a background thread. You shouldn't do any UI tasks there. On the other hand, the onProgressUpdate and onPreExecute run on the UI thread, so there you can change the progress bar:
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog.show();
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
mProgressDialog.setProgress(progress[0]);
}
}
}
Add the following permission in you manifest file .
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
i have tested in mobile too. its worked.
Try working with this code:
URL url;
long startTime = System.currentTimeMillis();
// Open a connection to that URL.
URLConnection ucon = null;
try {
url = new URL(
"http://java.net/downloads/jfjug/SCJP%20Sun%20Certified%20Programmer%20for%20Java%206-0071591060.pdf");
ucon = url.openConnection();
Log.i("", "image download beginning: " + url);
ucon.setReadTimeout(TIMEOUT_CONNECTION);
ucon.setConnectTimeout(TIMEOUT_SOCKET);
// Define InputStreams to read from the URLConnection.
// uses 3KB download buffer
InputStream is = ucon.getInputStream();
BufferedInputStream inStream = new BufferedInputStream(is, 1024 * 5);
FileOutputStream outStream = new FileOutputStream(
"mnt/sdcard/example.pdf");
byte[] buff = new byte[5 * 1024];
int len;
while ((len = inStream.read(buff)) != -1) {
outStream.write(buff, 0, len);
}
outStream.flush();
outStream.close();
inStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
As per the java doc for public int read (byte\[\] buffer, int offset, int length) method it returns
the number of bytes actually read or -1 if the end of the stream has
been reached.
So you should check for -1 rather then 0.
Change your while loop from
while ((len = inputStream.read(buffer)) > 0) {
fileOutput.write(buffer, 0, len);
}
to following
while ((len = inputStream.read(buffer)) != -1) {
fileOutput.write(buffer, 0, len);
}
And as pointed out in comments you should do this in background thread or AsyncTask...
EDIT1:
Can you put some logs to see the point of error.. like if the input stream is getting opened or not... Also after the call to connect check for the HTTP response code by calling getResponseCode() method if the response code is 200 then only create the file..

Read/Write String from/to a File in Android

I want to save a file to the internal storage by getting the text inputted from EditText. Then I want the same file to return the inputted text in String form and save it to another String which is to be used later.
Here's the code:
package com.omm.easybalancerecharge;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText num = (EditText) findViewById(R.id.sNum);
Button ch = (Button) findViewById(R.id.rButton);
TelephonyManager operator = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String opname = operator.getNetworkOperatorName();
TextView status = (TextView) findViewById(R.id.setStatus);
final EditText ID = (EditText) findViewById(R.id.IQID);
Button save = (Button) findViewById(R.id.sButton);
final String myID = ""; //When Reading The File Back, I Need To Store It In This String For Later Use
save.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
//Get Text From EditText "ID" And Save It To Internal Memory
}
});
if (opname.contentEquals("zain SA")) {
status.setText("Your Network Is: " + opname);
} else {
status.setText("No Network");
}
ch.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
//Read From The Saved File Here And Append It To String "myID"
String hash = Uri.encode("#");
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:*141*" + /*Use The String With Data Retrieved Here*/ num.getText()
+ hash));
startActivity(intent);
}
});
}
I have included comments to help you further analyze my points as to where I want the operations to be done/variables to be used.
Hope this might be useful to you.
Write File:
private void writeToFile(String data,Context context) {
try {
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(context.openFileOutput("config.txt", Context.MODE_PRIVATE));
outputStreamWriter.write(data);
outputStreamWriter.close();
}
catch (IOException e) {
Log.e("Exception", "File write failed: " + e.toString());
}
}
Read File:
private String readFromFile(Context context) {
String ret = "";
try {
InputStream inputStream = context.openFileInput("config.txt");
if ( inputStream != null ) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String receiveString = "";
StringBuilder stringBuilder = new StringBuilder();
while ( (receiveString = bufferedReader.readLine()) != null ) {
stringBuilder.append("\n").append(receiveString);
}
inputStream.close();
ret = stringBuilder.toString();
}
}
catch (FileNotFoundException e) {
Log.e("login activity", "File not found: " + e.toString());
} catch (IOException e) {
Log.e("login activity", "Can not read file: " + e.toString());
}
return ret;
}
For those looking for a general strategy for reading and writing a string to file:
First, get a file object
You'll need the storage path. For the internal storage, use:
File path = context.getFilesDir();
For the external storage (SD card), use:
File path = context.getExternalFilesDir(null);
Then create your file object:
File file = new File(path, "my-file-name.txt");
Write a string to the file
FileOutputStream stream = new FileOutputStream(file);
try {
stream.write("text-to-write".getBytes());
} finally {
stream.close();
}
Or with Google Guava
String contents = Files.toString(file, StandardCharsets.UTF_8);
Read the file to a string
int length = (int) file.length();
byte[] bytes = new byte[length];
FileInputStream in = new FileInputStream(file);
try {
in.read(bytes);
} finally {
in.close();
}
String contents = new String(bytes);
Or if you are using Google Guava
String contents = Files.toString(file,"UTF-8");
For completeness I'll mention
String contents = new Scanner(file).useDelimiter("\\A").next();
which requires no libraries, but benchmarks 50% - 400% slower than the other options (in various tests on my Nexus 5).
Notes
For each of these strategies, you'll be asked to catch an IOException.
The default character encoding on Android is UTF-8.
If you are using external storage, you'll need to add to your manifest either:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
or
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Write permission implies read permission, so you don't need both.
public static void writeStringAsFile(final String fileContents, String fileName) {
Context context = App.instance.getApplicationContext();
try {
FileWriter out = new FileWriter(new File(context.getFilesDir(), fileName));
out.write(fileContents);
out.close();
} catch (IOException e) {
Logger.logError(TAG, e);
}
}
public static String readFileAsString(String fileName) {
Context context = App.instance.getApplicationContext();
StringBuilder stringBuilder = new StringBuilder();
String line;
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(new File(context.getFilesDir(), fileName)));
while ((line = in.readLine()) != null) stringBuilder.append(line);
} catch (FileNotFoundException e) {
Logger.logError(TAG, e);
} catch (IOException e) {
Logger.logError(TAG, e);
}
return stringBuilder.toString();
}
Just a a bit modifications on reading string from a file method for more performance
private String readFromFile(Context context, String fileName) {
if (context == null) {
return null;
}
String ret = "";
try {
InputStream inputStream = context.openFileInput(fileName);
if ( inputStream != null ) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
int size = inputStream.available();
char[] buffer = new char[size];
inputStreamReader.read(buffer);
inputStream.close();
ret = new String(buffer);
}
}catch (Exception e) {
e.printStackTrace();
}
return ret;
}
The Kotlin way by using builtin Extension function on File
Write: yourFile.writeText(textFromEditText)
Read: yourFile.readText()
check the below code.
Reading from a file in the filesystem.
FileInputStream fis = null;
try {
fis = context.openFileInput(fileName);
InputStreamReader isr = new InputStreamReader(fis);
// READ STRING OF UNKNOWN LENGTH
StringBuilder sb = new StringBuilder();
char[] inputBuffer = new char[2048];
int l;
// FILL BUFFER WITH DATA
while ((l = isr.read(inputBuffer)) != -1) {
sb.append(inputBuffer, 0, l);
}
// CONVERT BYTES TO STRING
String readString = sb.toString();
fis.close();
catch (Exception e) {
} finally {
if (fis != null) {
fis = null;
}
}
below code is to write the file in to internal filesystem.
FileOutputStream fos = null;
try {
fos = context.openFileOutput(fileName, Context.MODE_PRIVATE);
fos.write(stringdatatobestoredinfile.getBytes());
fos.flush();
fos.close();
} catch (Exception e) {
} finally {
if (fos != null) {
fos = null;
}
}
I think this will help you.
I'm a bit of a beginner and struggled getting this to work today.
Below is the class that I ended up with. It works but I was wondering how imperfect my solution is. Anyway, I was hoping some of you more experienced folk might be willing to have a look at my IO class and give me some tips. Cheers!
public class HighScore {
File data = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator);
File file = new File(data, "highscore.txt");
private int highScore = 0;
public int readHighScore() {
try {
BufferedReader br = new BufferedReader(new FileReader(file));
try {
highScore = Integer.parseInt(br.readLine());
br.close();
} catch (NumberFormatException | IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
try {
file.createNewFile();
} catch (IOException ioe) {
ioe.printStackTrace();
}
e.printStackTrace();
}
return highScore;
}
public void writeHighScore(int highestScore) {
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
bw.write(String.valueOf(highestScore));
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Kotlin
class FileReadWriteService {
private var context:Context? = ContextHolder.instance.appContext
fun writeFileOnInternalStorage(fileKey: String, sBody: String) {
val file = File(context?.filesDir, "files")
try {
if (!file.exists()) {
file.mkdir()
}
val fileToWrite = File(file, fileKey)
val writer = FileWriter(fileToWrite)
writer.append(sBody)
writer.flush()
writer.close()
} catch (e: Exception) {
Logger.e(classTag, e)
}
}
fun readFileOnInternalStorage(fileKey: String): String {
val file = File(context?.filesDir, "files")
var ret = ""
try {
if (!file.exists()) {
return ret
}
val fileToRead = File(file, fileKey)
val reader = FileReader(fileToRead)
ret = reader.readText()
reader.close()
} catch (e: Exception) {
Logger.e(classTag, e)
}
return ret
}
}
the first thing we need is the permissions in AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
so in an asyncTask Kotlin class, we treat the creation of the file
import android.os.AsyncTask
import android.os.Environment
import android.util.Log
import java.io.*
class WriteFile: AsyncTask<String, Int, String>() {
private val mFolder = "/MainFolder"
lateinit var folder: File
internal var writeThis = "string to cacheApp.txt"
internal var cacheApptxt = "cacheApp.txt"
override fun doInBackground(vararg writethis: String): String? {
val received = writethis[0]
if(received.isNotEmpty()){
writeThis = received
}
folder = File(Environment.getExternalStorageDirectory(),"$mFolder/")
if(!folder.exists()){
folder.mkdir()
val readME = File(folder, cacheApptxt)
val file = File(readME.path)
val out: BufferedWriter
try {
out = BufferedWriter(FileWriter(file, true), 1024)
out.write(writeThis)
out.newLine()
out.close()
Log.d("Output_Success", folder.path)
} catch (e: Exception) {
Log.d("Output_Exception", "$e")
}
}
return folder.path
}
override fun onPostExecute(result: String) {
super.onPostExecute(result)
if(result.isNotEmpty()){
//implement an interface or do something
Log.d("onPostExecuteSuccess", result)
}else{
Log.d("onPostExecuteFailure", result)
}
}
}
Of course if you are using Android above Api 23, you must handle the request to allow writing to device memory. Something like this
import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
class ReadandWrite {
private val mREAD = 9
private val mWRITE = 10
private var readAndWrite: Boolean = false
fun readAndwriteStorage(ctx: Context, atividade: AppCompatActivity): Boolean {
if (Build.VERSION.SDK_INT < 23) {
readAndWrite = true
} else {
val mRead = ContextCompat.checkSelfPermission(ctx, Manifest.permission.READ_EXTERNAL_STORAGE)
val mWrite = ContextCompat.checkSelfPermission(ctx, Manifest.permission.WRITE_EXTERNAL_STORAGE)
if (mRead != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(atividade, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), mREAD)
} else {
readAndWrite = true
}
if (mWrite != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(atividade, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), mWRITE)
} else {
readAndWrite = true
}
}
return readAndWrite
}
}
then in an activity, execute the call.
var pathToFileCreated = ""
val anRW = ReadandWrite().readAndwriteStorage(this,this)
if(anRW){
pathToFileCreated = WriteFile().execute("onTaskComplete").get()
Log.d("pathToFileCreated",pathToFileCreated)
}
We can use this code to write String to a file
public static void writeTextToFile(final String filename, final String data) {
File file = new File(filename);
try {
FileOutputStream stream = new FileOutputStream(file);
stream.write(data.getBytes());
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Then in the Main code, we use this, for example
writeTextToFile(getExternalFilesDir("/").getAbsolutePath() + "/output.txt", "my-example-text");
After that, check the file at Android/data/<package-name>/files.
The easiest way to append to a text file in kotlin:
val directory = File(context.filesDir, "LogsToSendToNextMunich").apply {
mkdirs()
}
val file = File(directory,"Logs.txt")
file.appendText("You new text")
If you want to just write to the file:
yourFile.writeText("You new text")
writing anything to the files, using bytes:
FileOutputStream(file).use {
it.write("Some text for example".encodeToByteArray())
}

Getting image from the Internet and setting to ImageView

I have an ImageView called tab1. My code looks this.
import java.io.InputStream;
import java.net.URL;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TabHost;
import android.widget.Toast;
public class Paikallissaa extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TabHost tabs = (TabHost) findViewById(R.id.tabhost);
tabs.setup();
TabHost.TabSpec spec = tabs.newTabSpec("tag1");
try {
ImageView iv = (ImageView) findViewById(R.id.tab1);
URL url = new URL("http://cdn.fmi.fi/weather-observations/products/finland/finland-weather-observations-map.png");
InputStream content = (InputStream) url.getContent();
Drawable d = Drawable.createFromStream(content, "src");
iv.setImageDrawable(d);
} catch (Exception e) {
Toast.makeText(this, "Error getting image: " + e, Toast.LENGTH_SHORT);
}
spec.setContent(R.id.tab1);
spec.setIndicator("Koko maa");
tabs.addTab(spec);
spec = tabs.newTabSpec("tag2");
spec.setContent(R.id.tab2);
spec.setIndicator("Raisio");
tabs.addTab(spec);
}
}
(Ash I suck with the code block thing...)
It wont update the image. What's wrong? It keeps showing the image I set there earlier in main.xml.
To do this i've been using a helper class that i found somewhere on the internet and modified a tiny bit. It takes care of caching the image and loading the image on a background thread.
Since your image changes on the server you might want to remove the caching portion of this code.
Usage:
ImageLoader loader = new ImageLoader(this);
loader.DisplayImage(String.format(headshotUrl, data.Id), this, headshot);
here it is:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Stack;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.widget.ImageView;
public class ImageLoader
{
public static String TAG = "xxx";
// the simplest in-memory cache implementation. This should be replaced with
// something like SoftReference or BitmapOptions.inPurgeable(since 1.6)
private HashMap<String, Bitmap> cache = new HashMap<String, Bitmap>();
private File cacheDir;
public ImageLoader(Context context)
{
photoLoaderThread.setPriority(Thread.NORM_PRIORITY - 1);
cacheDir = Utilities.GetCacheDir(context);
}
final int stub_id = R.drawable.face_placeholder;
public void DisplayImage(String url, Activity activity, ImageView imageView)
{
imageView.setTag(url);
Log.i(TAG, url);
if (cache.containsKey(url))
imageView.setImageBitmap(cache.get(url));
else
{
queuePhoto(url, activity, imageView);
imageView.setImageResource(stub_id);
}
}
private void queuePhoto(String url, Activity activity, ImageView imageView)
{
// This ImageView may be used for other images before. So there may be
// some old tasks in the queue. We need to discard them.
photosQueue.Clean(imageView);
PhotoToLoad p = new PhotoToLoad(url, imageView);
synchronized (photosQueue.photosToLoad)
{
photosQueue.photosToLoad.push(p);
photosQueue.photosToLoad.notifyAll();
}
// start thread if it's not started yet
if (photoLoaderThread.getState() == Thread.State.NEW)
photoLoaderThread.start();
}
private Bitmap getBitmap(String url)
{
// I identify images by hashcode. Not a perfect solution, good for the
// demo.
String filename = String.valueOf(url.hashCode());
File f = new File(cacheDir, filename);
// from SD cache
Bitmap b = decodeFile(f);
if (b != null)
return b;
// from web
try
{
Bitmap bitmap = null;
InputStream is = new URL(url).openStream();
OutputStream os = new FileOutputStream(f);
Utilities.CopyStream(is, os);
os.close();
bitmap = decodeFile(f);
return bitmap;
} catch (Exception ex)
{
ex.printStackTrace();
return null;
}
}
// decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f)
{
try
{
// decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
// Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE = 70;
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true)
{
if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
// decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e)
{
e.printStackTrace();
}
return null;
}
// Task for the queue
private class PhotoToLoad
{
public String url;
public ImageView imageView;
public PhotoToLoad(String u, ImageView i)
{
url = u;
imageView = i;
}
}
PhotosQueue photosQueue = new PhotosQueue();
public void stopThread()
{
photoLoaderThread.interrupt();
}
// stores list of photos to download
class PhotosQueue
{
private Stack<PhotoToLoad> photosToLoad = new Stack<PhotoToLoad>();
// removes all instances of this ImageView
public void Clean(ImageView image)
{
for (int j = 0; j < photosToLoad.size();)
{
if (photosToLoad.get(j).imageView == image)
photosToLoad.remove(j);
else
++j;
}
};
}
class PhotosLoader extends Thread
{
public void run()
{
try
{
while (true)
{
// thread waits until there are any images to load in the
// queue
if (photosQueue.photosToLoad.size() == 0)
synchronized (photosQueue.photosToLoad)
{
photosQueue.photosToLoad.wait();
}
if (photosQueue.photosToLoad.size() != 0)
{
PhotoToLoad photoToLoad;
synchronized (photosQueue.photosToLoad)
{
photoToLoad = photosQueue.photosToLoad.pop();
}
Bitmap bmp = getBitmap(photoToLoad.url);
cache.put(photoToLoad.url, bmp);
Object tag = photoToLoad.imageView.getTag();
if (tag != null && ((String) tag).equals(photoToLoad.url))
{
BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad.imageView);
Activity a = (Activity) photoToLoad.imageView.getContext();
a.runOnUiThread(bd);
}
}
if (Thread.interrupted())
break;
}
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
PhotosLoader photoLoaderThread = new PhotosLoader();
// Used to display bitmap in the UI thread
class BitmapDisplayer implements Runnable
{
Bitmap bitmap;
ImageView imageView;
public BitmapDisplayer(Bitmap b, ImageView i)
{
bitmap = b;
imageView = i;
}
public void run()
{
Log.i(TAG, "BitmapDisplayer run()");
if (bitmap != null)
imageView.setImageBitmap(bitmap);
else
imageView.setImageResource(stub_id);
}
}
public void clearCache()
{
// clear memory cache
cache.clear();
// clear SD cache
File[] files = cacheDir.listFiles();
for (File f : files)
f.delete();
}
}
in a utility class i have my GetCacheDir(...)
public static File GetCacheDir(Context context)
{
File cacheDir;
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
cacheDir = new File(android.os.Environment.getExternalStorageDirectory(), "com.example.app");
else
cacheDir = context.getCacheDir();
if (!cacheDir.exists())
cacheDir.mkdirs();
return cacheDir;
}
CopyStream function:
public static void CopyStream(InputStream is, OutputStream os)
{
final int buffer_size = 1024;
try
{
byte[] bytes = new byte[buffer_size];
for (;;)
{
int count = is.read(bytes, 0, buffer_size);
if (count == -1)
break;
os.write(bytes, 0, count);
}
} catch (Exception ex)
{
}
}
To get the image from the internet try the following,
HttpGet httpRequest = new HttpGet(URI.create("http://cdn.fmi.fi/weather-observations/products/finland/finland-weather-observations-map.png") );
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpclient.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity);
bmp = BitmapFactory.decodeStream(bufHttpEntity.getContent());
ImageView iv = (ImageView) findViewById(R.id.tab1);
iv.setImageBitmat(bmp);
httpRequest.abort();
This will download an image and set it to an image view, taken from an app I helped write. I stripped out some of the useless code that I was using, but the methods remain the same.
public void setImage(){
imageView.setImageURI(DownloadImage);
}
public String DownloadImage(){
string filepath = DownloadFromUrl("url","filename.png");
}
public String DownloadFromUrl(String imageURL, String fileName) {
File file = new File(PATH + fileName);
try {
URL url = new URL(imageURL);
long startTime = System.currentTimeMillis();
Log.d("ImageManager", "download begining");
Log.d("ImageManager", "download url:" + url);
Log.d("ImageManager", "downloaded file name:" + fileName);
/* Open a connection to that URL. */
URLConnection ucon = url.openConnection();
/*
* Define InputStreams to read from the URLConnection.
*/
InputStream is = ucon.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
/*
* Read bytes to the Buffer until there is nothing more to read(-1).
*/
ByteArrayBuffer baf = new ByteArrayBuffer(50);
int current = 0;
while ((current = bis.read()) != -1) {
baf.append((byte) current);
}
/* Convert the Bytes read to a String. */
FileOutputStream fos = new FileOutputStream(file);
fos.write(baf.toByteArray());
fos.close();
Log.d("ImageManager",
"download ready in"
+ ((System.currentTimeMillis() - startTime) / 1000)
+ " sec");
} catch (IOException e) {
Log.d("ImageManager", "Error: " + e);
}
return file.toString();
}

Categories