I'd like to create app which allows to download a picture using URL address and next, shows it on my screen.
Unfortunately, in LogCat is showed this error:
BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: sdcard/photoalbum/download_image.jpg: open failed: ENOENT (No such file or directory)
Download's progress, which is showing on screen, works really fast. Image has 12 KB.
But I see that this picture is not downloading on my phone (sdcard).
This is caused that I couldn't decode this stream?
I would be grateful if somebody know how to resolve/fix this problem?
Here is a code:
ImageView imageView;
String image_url = "http://montco.happeningmag.com/wp-content/uploads/2015/04/run-150x150.jpg";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
imageView = (ImageView) findViewById(R.id.image_view);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DownloadTask downloadTask = new DownloadTask();
downloadTask.execute(image_url);
}
});
}
// how to create an assign task do download this image
class DownloadTask extends AsyncTask<String,Integer,String> // second type is Integer because this is from 'int progress', third is String because this is the return ("Download Complete...")
{
// progress bar to display this download
ProgressDialog progressDialog;
#Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setTitle("Download in Progress...");
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMax(100);
progressDialog.setProgress(0);
progressDialog.show();
}
#Override
protected String doInBackground(String... params) {
// how is the maximum size of this file, we need some variable:
int file_length = 0;
String path = params[0]; // we get this URL , 0(zero) index of this argument
// how image_url on this variable call "path"
try {
URL url = new URL(path);
URLConnection urlConnection = url.openConnection();
urlConnection.connect();
file_length = urlConnection.getContentLength();
// we need a folder to storage this download image
File new_folder = new File("sdcard/photoalbum");
if(!new_folder.exists())
{
new_folder.mkdir(); // we create new folder if 'photoalbum' doesnt exist in sdcard
}
// how to put some file inside this folder
File input_file = new File(new_folder,"downloaded_image.jpg");
// how to create input STREAM to read information data from url
InputStream inputStream = new BufferedInputStream(url.openStream(),8192); // we need input stream with some buffer. 8192(8 KB) (input stream
// now I want to read informations in one kb so I need byte variable
byte[] data = new byte[1024]; // it will read info to 1 KB
// before read information we need some variable
int total = 0;
int count = 0;
// we need output stream object to write a data
OutputStream outputStream = new FileOutputStream(input_file); // because outputStream is available in input_file
// we need write information to outputStream
while((count = inputStream.read())!=-1) //loop executes until the value became (-1)
{
// how to update value from a variable total
total += count;
outputStream.write(data,0,count); // data is available on the Byte variable data; offset; count
// how to display a progress bar: we need to call publish progress method and specify special value for this progress
int progress = (int) total*100/file_length;
publishProgress(progress);
}
// how to close Stream
inputStream.close();
outputStream.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// after finished our job we need to return some result
return "Download Complete...";
}
#Override
protected void onProgressUpdate(Integer... values) {
progressDialog.setProgress(values[0]); // this will update the progress bar
}
#Override
protected void onPostExecute(String result) {
// after finishing job, we need to hide a progress bar
progressDialog.hide();
// how to display some result
Toast.makeText(getApplicationContext(),result,Toast.LENGTH_LONG).show();
// how to put image into imageView
String path = "sdcard/photoalbum/download_image.jpg";
// how to set this image in imageView
imageView.setImageDrawable(Drawable.createFromPath(path));
}
}
File new_folder = new File("sdcard/photoalbum");
if(!new_folder.exists()){
new_folder.mkdir(); // we create new folder if 'photoalbum' doesnt exist in sdcard
}
Try to modify the upper code as follow:
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
|| !Environment.isExternalStorageRemovable()) {
File new_folder = new File(Environment.getExternalStorageDirectory().toString() + File.separator + "photoalbum");
if(!new_folder.exists()){
new_folder.mkdirs(); // we create new folder if 'photoalbum' doesnt exist in sdcard
}
}
Related
I am trying desperately to read a file from Android Studio asset folder. The file is "ok.txt" and contains the string: yo chicken mcgriddle fiddle fiddle.
Per this video: https://youtu.be/1CHDASXojNQ and stackoverflow browsing, this is the solution I came up with:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
tv_text = (TextView) findViewById(R.id.nameView);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
tv_text.setText(LoadData("ok.txt"));
}
public String LoadData(String inFile) {
String tContents = "";
try {
InputStream stream = getAssets().open(inFile);
int size = stream.available();
byte[] buffer = new byte[size];
stream.read(buffer);
stream.close();
tContents = new String(buffer);
} catch (IOException e) {
// Handle exceptions here
}
return tContents;
}
});
}
}
I am inclined to believe that the code works, but, it does not return the String. In the app, it returns a blank message in the place of the textview's "hello world" placeholder after clicking the button. I thought it was due to the limitation of the textview so I modified the constraint size, but the blank persists. Anybody know what's up?
I am trying to make an app which downloads the pdf file from the internet and saves it to Downloads folder. After downloading the pdf,instead of opening a 3rd party pdf app , I want it to render in the app itself.( I have done downloading and saving in Downloads folder part). For this, I have to use PDFRendered. But the problem I am facing is that I am a newbie and after looking at some tutorials , I am able to render a pdf properly but only when it is present in the assets folder. Downloaded pdf is present in the Downloads folder. Is there any way in which I can use the pdf from Downloads folder and render it in the app itself instead of pre-defining the pdf file in the assets folder?
I have tried downloading and saving file in Downloading folder and I have successfully done it but I'm unable to use the file to render as it is not inside assets folder.
//Code which is successfully rendering pdf from assets folder. How to
//use it to render pdf from Download folder?
public class PdfRender extends AppCompatActivity {
#BindView(R.id.pdf_image) ImageView imageViewPdf;
#BindView(R.id.button_pre_doc) FloatingActionButton prePageButton;
#BindView(R.id.button_next_doc) FloatingActionButton nextPageButton;
private static final String FILENAME = Environment.DIRECTORY_DOWNLOADS+"/a.pdf";
private int pageIndex;
private PdfRenderer pdfRenderer;
private PdfRenderer.Page currentPage;
private ParcelFileDescriptor parcelFileDescriptor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pdf_render);
ButterKnife.bind(this);
pageIndex = 0;
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Override
protected void onStart() {
super.onStart();
try {
openRenderer(getApplicationContext());
showPage(pageIndex);
} catch (IOException e) {
e.printStackTrace();
}
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Override
public void onStop() {
try {
closeRenderer();
} catch (IOException e) {
e.printStackTrace();
}
super.onStop();
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#OnClick(R.id.button_pre_doc)
public void onPreviousDocClick(){
showPage(currentPage.getIndex() - 1);
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#OnClick(R.id.button_next_doc)
public void onNextDocClick(){
showPage(currentPage.getIndex() + 1);
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void openRenderer(Context context) throws IOException {
// In this sample, we read a PDF from the assets directory.
File file = new File(context.getCacheDir(), FILENAME);
if (!file.exists()) {
// Since PdfRenderer cannot handle the compressed asset file directly, we copy it into
// the cache directory.
InputStream asset = context.getAssets().open(FILENAME);
FileOutputStream output = new FileOutputStream(file);
final byte[] buffer = new byte[1024];
int size;
while ((size = asset.read(buffer)) != -1) {
output.write(buffer, 0, size);
}
asset.close();
output.close();
}
parcelFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
// This is the PdfRenderer we use to render the PDF.
if (parcelFileDescriptor != null) {
pdfRenderer = new PdfRenderer(parcelFileDescriptor);
}
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void closeRenderer() throws IOException {
if (null != currentPage) {
currentPage.close();
}
pdfRenderer.close();
parcelFileDescriptor.close();
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void showPage(int index) {
if (pdfRenderer.getPageCount() <= index) {
return;
}
// Make sure to close the current page before opening another one.
if (null != currentPage) {
currentPage.close();
}
// Use `openPage` to open a specific page in PDF.
currentPage = pdfRenderer.openPage(index);
// Important: the destination bitmap must be ARGB (not RGB).
Bitmap bitmap = Bitmap.createBitmap(currentPage.getWidth(), currentPage.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.
currentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
// We are ready to show the Bitmap to user.
imageViewPdf.setImageBitmap(bitmap);
updateUi();
}
/**
* Updates the state of 2 control buttons in response to the current page index.
*/
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void updateUi() {
int index = currentPage.getIndex();
int pageCount = pdfRenderer.getPageCount();
prePageButton.setEnabled(0 != index);
nextPageButton.setEnabled(index + 1 < pageCount);
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public int getPageCount() {
return pdfRenderer.getPageCount();
}
}
Update-: I tried to make changes to a working code of Rendering app and edit openRenderer() to make changes and give my file name and location as below but still the pdf file dosen't open even thugh it is detected (checked in logs using file.exists()) . Any way to find solution to this problem?
`private void openRenderer(Context context) throws IOException {
File file = new File("storage/emulated/0/Download/" + FILENAME);
if (!file.exists()) {
Log.e("testit", "Not exists");
FileInputStream asset = new FileInputStream(file);
FileOutputStream output = new FileOutputStream(file);
final byte[] buffer = new byte[1024];
int size;
while ((size = asset.read(buffer)) != -1) {
output.write(buffer, 0, size);
}
asset.close();
output.close();
}
parcelFileDescriptor = ParcelFileDescriptor.open(file,ParcelFileDescriptor.MODE_READ_ONLY);
// This is the PdfRenderer we use to render the PDF.
if (parcelFileDescriptor != null) {
pdfRenderer = new PdfRenderer(parcelFileDescriptor);
}
}`
I get the following error in logs
`java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.pdf.PdfRenderer.close()' on a null object reference`
Expected results are fetch and download the pdf from the internet. Click on a button which downloads and immediately after downloading renders the pdf in the app itself and users can view the pdf in the app itself without the use of any 3rd party pdf app or a webview(for users after or on 5.0).
I'm trying to use an Activity which displays a random object from my array. This object is passed in from an intent.
I am trying to use an image for each of these objects and then display the correct image for the correct object.
So far I've been using the drawable folder to hold my images and then loading them in through the XML however this stops me using multiple images for the same ImageView.
I tried using imageview.setImageResource(R.drawable.imagename); but that doesn't seem to like loading in for some reason.
Do I need to make a new activity for each of the objects in this case?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_random_race);
TextView name = (TextView)findViewById(R.id.raceName);
Intent secondIntent = getIntent();
Race message = (Race)secondIntent.getSerializableExtra("RACE");
ImageView image = (ImageView) findViewById(R.id.raceImage);
image.setImageResource(R.drawable.hacan);
image.setImageBitmap(imageToBitmapImage(message, image));
name.setText(message.getName());
}
Bytes to Bitmap method
public Bitmap imageToBitmapImage (Race message, ImageView image){
Bitmap bmp;
try {
FileInputStream in = new FileInputStream(message.getImageName());
BufferedInputStream buffer = new BufferedInputStream(in);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int input = buffer.read();
while (input != -1){
baos.write(input);
input = buffer.read();
}
byte[] bytes = baos.toByteArray();
bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
return bmp;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
Class of each object I'm talking about.
public class Race implements Serializable {
private String name;
private String imageName; //name of file within drawable
As #XavierFalempin commented, you can't access ressources through a file stream. Using setImageResource() should work. Following this answer your onCreate() method should look something like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_random_race);
TextView name = (TextView)findViewById(R.id.raceName);
Intent secondIntent = getIntent();
Race message = (Race)secondIntent.getSerializableExtra("RACE");
ImageView image = (ImageView) findViewById(R.id.raceImage);
image.setImageResource(getResources().getIdentifier(message.getImageName(),
"drawable",
getPackageName()));
name.setText(message.getName());
}
Since google Drive can not download a file of more than 25 MB, as it requests the authorization of the user from an HTML page, I thought that it was necessary for these files to display the page "virus warning" in a webView in my App. So I created this small sample in Android studio to test. It is quite simple a MainActivity and an activity.xml containing a simple WebView:
public class MainActivity extends AppCompatActivity {
private static final int WRITE_SDCARD_REQUEST_CODE = 12;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// permission to write file on internal storage ....
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
WRITE_SDCARD_REQUEST_CODE);
} else {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
WRITE_SDCARD_REQUEST_CODE);
}
}
else {
// launch my webPage and webClient withe the given url of my file
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.loadUrl("https://drive.google.com/uc?export=download&id=0B4fwFC8FCSQGGTZfbHYwczBXVjg");
myWebView.setWebViewClient(new MyWebViewClient());
}
}
private class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// return after valid with "Download anyway " button
Log.i("URL",url);//<-- url result: https://drive.google.com/uc?export=download&confirm=LoXi&id=0B4fwFC8FCSQGGTZfbHYwczBXVjg
//with "confirm=LoXi" Added to the original link
// so i try to download this new confirmed url given by Google Drive warning page
// But the link is not valid for download!!!!! Why????
DownloadFileFromURL dFURL = new DownloadFileFromURL();
dFURL.execute(url);
// I obtain a wrong file .... 36 Ko...not good!
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == WRITE_SDCARD_REQUEST_CODE)
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
WebView myWebView = (WebView) findViewById(R.id.webview);
// original link of file Google drive that i want to download
myWebView.loadUrl("https://drive.google.com/uc?export=download&id=0B4fwFC8FCSQXbTZfbHYwczBXVjg");
myWebView.setWebViewClient(new MyWebViewClient());
}
}
class DownloadFileFromURL extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Bar Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
}
/**
* Downloading file in background thread
* */
#Override
protected String doInBackground(String... f_url) {
int count;
try {
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
conection.connect();
// this will be useful so that you can show a tipical 0-100%
// progress bar
int lenghtOfFile = conection.getContentLength();
// download the file
InputStream input = new BufferedInputStream(url.openStream(),
8192);
// Output stream
OutputStream output = new FileOutputStream(Environment
.getExternalStorageDirectory().toString()
+ "/video.mp4");
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
// After this onProgressUpdate will be called
publishProgress("" + (int) ((total * 100) / lenghtOfFile));
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
/**
* Updating progress bar
* */
protected void onProgressUpdate(String... progress) {
// setting progress percentage
//pDialog.setProgress(Integer.parseInt(progress[0]));
}
/**
* After completing background task Dismiss the progress dialog
* **/
#Override
protected void onPostExecute(String file_url) {
// dismiss the dialog after the file was downloaded
//dismissDialog(progress_bar_type);
}
}
}
From the download link of my file of more than 25 MB (here 90 Mo) I display well the page "Virus Warning" of drive. After clicking on the download button "download anyway" I am able to get a modified link back in my WebClient. But this link does not seem valid. If I try to copy / paste it in chrome I return to the same page of the "virus Warning" !!! Why??
When I right click on the "download anyway" button to copy the link, this link is the same form that I get by my WebClient but the part "confirm=XXXX" not, and it works and gives me access to the download!
Could you give me your opinions and suggestions?
Thank you.
I finally solved the problem by managing the cookies in my WebViewClient and using DownloadManager:``
private class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// prevent other actions on page
if (url.contains("export=download&confirm")){
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
Uri source = Uri.parse(url);
DownloadManager.Request request = new DownloadManager.Request(source);
String cookie = CookieManager.getInstance().getCookie(url);
request.addRequestHeader("Cookie", cookie);
request.addRequestHeader("User-Agent", view.getSettings().getUserAgentString());
request.addRequestHeader("Accept", "text/html, application/xhtml+xml, *" + "/" + "*");
request.addRequestHeader("Accept-Language", "en-US,en;q=0.7,he;q=0.3");
request.addRequestHeader("Referer", url);
request.setDestinationInExternalPublicDir("/","video.mp4");
manager.enqueue(request);
}else {
// a keyEvent back listener should be implemented
myWebView.loadUrl(url);
}
return true;
}
#Override
public void onPageFinished(WebView view, String url){
}
}
I hope it will help.
So Im having trouble using Microsoft's Emotion API for Android. I have no issues with regards to running the Face API; Im able to get the face rectangles but I am not able to get it working on the emotion api. I am taking images using the builtin Android camera itself. Here is the code I am using:
private void detectAndFrame(final Bitmap imageBitmap)
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
imageBitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
ByteArrayInputStream inputStream =
new ByteArrayInputStream(outputStream.toByteArray());
AsyncTask<InputStream, String, List<RecognizeResult>> detectTask =
new AsyncTask<InputStream, String, List<RecognizeResult>>() {
#Override
protected List<RecognizeResult> doInBackground(InputStream... params) {
try {
Log.e("i","Detecting...");
faces = faceServiceClient.detect(
params[0],
true, // returnFaceId
false, // returnFaceLandmarks
null // returnFaceAttributes: a string like "age, gender"
);
if (faces == null)
{
Log.e("i","Detection Finished. Nothing detected");
return null;
}
Log.e("i",
String.format("Detection Finished. %d face(s) detected",
faces.length));
ImageView imageView = (ImageView)findViewById(R.id.imageView);
InputStream stream = params[0];
com.microsoft.projectoxford.emotion.contract.FaceRectangle[] rects = new com.microsoft.projectoxford.emotion.contract.FaceRectangle[faces.length];
for (int i = 0; i < faces.length; i++) {
com.microsoft.projectoxford.face.contract.FaceRectangle rect = faces[i].faceRectangle;
rects[i] = new com.microsoft.projectoxford.emotion.contract.FaceRectangle(rect.left, rect.top, rect.width, rect.height);
}
List<RecognizeResult> result;
result = client.recognizeImage(stream, rects);
return result;
} catch (Exception e) {
Log.e("e", e.getMessage());
Log.e("e", "Detection failed");
return null;
}
}
#Override
protected void onPreExecute() {
//TODO: show progress dialog
}
#Override
protected void onProgressUpdate(String... progress) {
//TODO: update progress
}
#Override
protected void onPostExecute(List<RecognizeResult> result) {
ImageView imageView = (ImageView)findViewById(R.id.imageView);
imageView.setImageBitmap(drawFaceRectanglesOnBitmap(imageBitmap, faces));
MediaStore.Images.Media.insertImage(getContentResolver(), imageBitmap, "AnImage" ,"Another image");
if (result == null) return;
for (RecognizeResult res: result) {
Scores scores = res.scores;
Log.e("Anger: ", ((Double)scores.anger).toString());
Log.e("Neutral: ", ((Double)scores.neutral).toString());
Log.e("Happy: ", ((Double)scores.happiness).toString());
}
}
};
detectTask.execute(inputStream);
}
I keep getting the error Post Request 400, indicating some sort of issue with the JSON or the face rectangles. But I'm not sure where to start debugging this issue.
You're using the stream twice, so the second time around you're already at the end of the stream. So either you can reset the stream, or, simply call the emotion API without rectangles (ie skip the call to the face API.) The emotion API will determine the face rectangles for you.