why is pdf from internal storage not showing in webview - android

I have a .pdf file (which can change content daily, so must be downloaded daily) on my server which is downloaded to the device using Volley. The api uses authentication tokens.
I can successfully call the web service and write the pdf (byte[]) to my app's internal storage by using context.getExternalFilesDir.
The problem i am having is once the pdf is saved and i contruct the path, the webView will not show the pdf. The webView is working fine as i have done a test by placing a test html in the project's raw directory. The webView can display this fine.
The following does not load the pdf.
webView.loadUrl("file://" + f2.getAbsolutePath());
f2 path on my device is
f2.getAbsolutePath() = /storage/emulated/0/Android/data/com.xxxx.rrx/files/careplans/careplan.pdf
There seems to be no error but the pdf does not load.
What i have tried:
i've tried changing the webSettings for the webView to allow file access.
WebSettings webViewSettings = webView.getSettings();
// Setting this off for security. Off by default for SDK versions >= 16.
webViewSettings.setAllowFileAccessFromFileURLs(true);
// Off by default, deprecated for SDK versions >= 30.
webViewSettings.setAllowUniversalAccessFromFileURLs(true);
// Keeping these off is less critical but still a good idea, especially if your app is not
// using file:// or content:// URLs.
webViewSettings.setAllowFileAccess(true);
webViewSettings.setAllowContentAccess(true);
Does anyone have any ideas why the webview does not show the pdf when it is stored in the app's own storage?
here is my complete class.
import android.app.DownloadManager;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Base64;
import android.util.Log;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.android.volley.VolleyError;
import org.json.JSONObject;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
public class DownloadCarePlanActivity extends AppCompatActivity {
private static final String TAG = DownloadCarePlanActivity.class.getSimpleName();
DownloadManager manager;
long reference;
String url;
Context context;
String fileName;
WebView webView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.downloadcareplan_activity);
Log.e(TAG, "inside onCreate" );
context = getApplicationContext();
webView = (WebView)findViewById(R.id.webViewCareplan);
url = "https://xxx/api/xxx/careplan/1";
WebServicesForWebApi webServices = new WebServicesForWebApi(DownloadCarePlanActivity.this, new WebServicesForWebApi.IResultForFile() {
#Override
public void notifySuccess(byte[] response, String responseString) {
//responseString = responseString.replace('\\', ' ');
Log.e(TAG, "formatted result for pdf webservice = " + response);
byte[] result;
if(response != null){
try {
byte[] bytes = response;
saveToFile(bytes, "careplan.pdf");
}catch (Exception e){
Toast.makeText(DownloadCarePlanActivity.this, "Error downloading pdf and saving it", Toast.LENGTH_LONG).show();
}
}
}
#Override
public void notifyError(VolleyError error) {
Toast.makeText(DownloadCarePlanActivity.this, "There was a problem in sendFireBaseTokenToServerWAPI", Toast.LENGTH_LONG).show();
}
});
JSONObject js = new JSONObject();
/*try {
js.put("carerId", "0");
js.put("phoneId", fireBaseToken);
} catch (JSONException e) {
e.printStackTrace();
}*/
webServices.makeWebApiPostForFile(url, js);
}//end of onCreate
public void saveToFile(byte[] byteArray, String pFileName){
//File f = new File(Environment.getExternalStorageDirectory() + "/careplans");
File f = getAbsoluteFile("/careplans", context);
Log.e(TAG, "f.path = " + f.getAbsolutePath());
if(f.isDirectory()){
f.delete();
}
if (!f.isDirectory()) {
f.mkdir();
}
//String fileName = Environment.getExternalStorageDirectory() + "/careplans/" + pFileName;
fileName = f.getAbsolutePath() + "/" + pFileName;
Log.e(TAG, "String fileName = " + fileName);
try {
FileOutputStream fPdf = new FileOutputStream(fileName);
fPdf.write(byteArray);
fPdf.flush();
fPdf.close();
Toast.makeText(this, "File successfully saved", Toast.LENGTH_LONG).show();
try {
File f2 = new File(fileName);
Log.e(TAG, "f2.getAbsolutePath() = " + f2.getAbsolutePath());
Log.e(TAG, "f2.getCanonicalPath() = " + f2.getCanonicalPath());
Log.e(TAG, "loading file in webview" );
WebSettings webViewSettings = webView.getSettings();
// Setting this off for security. Off by default for SDK versions >= 16.
webViewSettings.setAllowFileAccessFromFileURLs(true);
// Off by default, deprecated for SDK versions >= 30.
webViewSettings.setAllowUniversalAccessFromFileURLs(true);
// Keeping these off is less critical but still a good idea, especially if your app is not
// using file:// or content:// URLs.
webViewSettings.setAllowFileAccess(true);
webViewSettings.setAllowContentAccess(true);
webView.loadUrl("file://" + f2.getAbsolutePath());
//webView.loadUrl("file:///android_res/raw/index.html");
Log.e(TAG, "finished loading file in webview" );
}catch(Exception e){
final Writer result = new StringWriter();
final PrintWriter printWriter = new PrintWriter(result);
e.printStackTrace(printWriter);
String stacktrace = result.toString();
printWriter.close();
Log.e(TAG, "stack = " + stacktrace);
}
} catch (FileNotFoundException e) {
Toast.makeText(this, "File create error", Toast.LENGTH_LONG).show();
} catch (IOException e) {
Toast.makeText(this, "File write error", Toast.LENGTH_LONG).show();
}
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
}
private File getAbsoluteFile(String relativePath, Context context) {
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
return new File(context.getExternalFilesDir(null), relativePath);
} else {
return new File(context.getFilesDir(), relativePath);
}
}
}

well, WebView is designed to open web pages, PDF isn't such content type... yeah, desktop browser can do it, even some mobile ones, but this is additional feature. not available in WebView, you have to handle such file by yourself (e.g. using PdfRenderer). another way is to use some library, first example from search engine: AndroidPdfViewer on GitHub
edit: just realised that your PDF is local only, so below probably isn't an option for you...
way simpler would be to use some web application, which can read PDF and show it as a web page, readable by WebView. for example try to load below URL
String pdfUrl = "https://docs.google.com/gview?embedded=true&url=" + realPdfUrl;

Related

Bitmap saved as black image sometimes for same bitmap

I know this was a common issue, but I have tried different suggestion, and still no solution.
My issue is that the bitmap is being displayed correctly, however SOMETIMES it saves as a black bitmap, while other times it saves correctly.
Can anyone see what I have done and tell me where I can be going wrong?
I have looked at most of the other StackOverflow questions.
The following is my code, which encodes the clip board text into a QR code and attempts to save the qr code generated.
Thank you!
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.text.ClipboardManager;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import java.io.File;
import java.io.FileOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
//import android.content.ClipboardManager;
public class BarcodeWriter extends AppCompatActivity {
ImageLoader imgLoader;
ImageView qrImg;
String copiedStr;
TextView qrTxt;
ClipboardManager clipboard;
String BASE_QR_URL = "http://chart.apis.google.com/chart?cht=qr&chs=400x400&chld=M&choe=UTF-8&chl=";
String fullUrl = BASE_QR_URL;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.barcode_writer);
DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
.cacheInMemory(true)
.cacheOnDisk(true)
.build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
.defaultDisplayImageOptions(defaultOptions)
.build();
imgLoader = ImageLoader.getInstance(); // Do it on Application start
imgLoader.init(config);
qrImg = (ImageView)findViewById(R.id.qrImg);
qrTxt = (TextView)findViewById(R.id.qrTxt);
clipboard = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);
/*
* clipboard.getText() is now deprecated. But I am going to use it here
* because the new way of doing the same thing only works on API lvl 11+
* Since I want this application to support API lvl 4+ we have to use
* the old method.
*/
CharSequence clipTxt = clipboard.getText();
//This is the new, non-deprecated way of getting text from the Clipboard.
//CharSequence clipTxt = clipboard.getPrimaryClip().getItemAt(0).getText();
//If the clipboard has text, and it is more than 0 characters.
if((null != clipTxt) && (clipTxt.length() > 0)){
try {
qrTxt.setText(clipTxt);
copiedStr = clipTxt.toString();
fullUrl += URLEncoder.encode(copiedStr, "UTF-8");
//imgLoader.displayImage(fullUrl, qrImg);
ImageLoader.getInstance().displayImage(fullUrl, qrImg, defaultOptions); // Incoming options will be used
qrImg.setDrawingCacheEnabled(true);
qrImg.measure(View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY));
qrImg.layout(0, 0, qrImg.getMeasuredWidth(), qrImg.getMeasuredHeight());
qrImg.buildDrawingCache();
Bitmap bm = Bitmap.createBitmap(qrImg.getDrawingCache());
qrImg.setDrawingCacheEnabled(false); // clear drawing cache
try {
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/DCIM/QR codes");
myDir.mkdirs();
String fname = clipTxt+".png";
File file = new File (myDir, fname);
if (file.exists ()) file.delete ();
try {
FileOutputStream out = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.PNG, 100, out);
Toast.makeText(BarcodeWriter.this, "Image Saved", Toast.LENGTH_SHORT).show();
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(file);
mediaScanIntent.setData(contentUri);
getApplicationContext().sendBroadcast(mediaScanIntent);
Toast.makeText(this,"QR Code showing "+clipTxt,Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(this, "Error occurred. Please try again later.",
Toast.LENGTH_SHORT).show();
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{ //If no text display a dialog.
Toast.makeText(this,"No text in clipboard",Toast.LENGTH_SHORT).show();
}
}
}
Your code seems to be fine, the only thing that I saw is that you are getting you Bitmap from and external URL with Universal Image Loader instantly after calling displayImage. So is possible that for some delay in the network sometimes your ImageView still doesn't have the entire image and can make your bitmap saved as black.
Please try moving your all code bellow ImageLoader.getInstance().displayImage inside the onLoadingComplete like this:
ImageLoader.getInstance().displayImage(fullUrl, qrImg, defaultOptions, new SimpleImageLoadingListener()
{
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
ImageLoader.getInstance().displayImage(fullUrl, qrImg, defaultOptions,null);
qrImg.setDrawingCacheEnabled(true);
...
catch (Exception e) {
Toast.makeText(this, "Error occurred. Please try again later.",
Toast.LENGTH_SHORT).show();
}
}
});
Hope this help!!

Create, write and display PDF file in android app

I have an android app which is basically a form to accept user input. This input is stored in a database. But I want to create a pdf file with the information a user enters and and display it so that the user can print the file or save the file to their android note tab. What is the best way to go about it. I have seen iText around but this does not render the file. I found this code online and I tested it to understand the concept of pdf creation. This uses Lowagie 2.1.7
package com.example.sweetiean.androidpdfdemo;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.Uri;
import android.os.Environment;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.HeaderFooter;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Phrase;
import com.lowagie.text.pdf.PdfWriter;
import com.lowagie.text.Image;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class MainActivity extends ActionBarActivity {
private Button createPDF , openPDF;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
createPDF = (Button)findViewById(R.id.button1);
createPDF.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
createPDF();
}
});
openPDF = (Button)findViewById(R.id.button2);
openPDF.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
openPdf();
}
});
}
public void createPDF()
{
Document doc = new Document();
try {
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/PDF";
File dir = new File(path);
if(!dir.exists())
dir.mkdirs();
Log.d("PDFCreator", "PDF Path: " + path);
File file = new File(dir, "demo.pdf");
FileOutputStream fOut = new FileOutputStream(file);
PdfWriter.getInstance(doc, fOut);
//open the document
doc.open();
/* Create Paragraph and S`enter code here`et Font */
Paragraph p1 = new Paragraph("Hi! I am Generating my first PDF using DroidText");
/* Create Set Font and its Size */
Font paraFont= new Font(Font.HELVETICA);
paraFont.setSize(16);
p1.setAlignment(Paragraph.ALIGN_CENTER);
p1.setFont(paraFont);
//add paragraph to document
doc.add(p1);
Paragraph p2 = new Paragraph("This is an example of a simple paragraph");
/* You can also SET FONT and SIZE like this */
Font paraFont2= new Font(Font.COURIER,14.0f, Color.GREEN);
p2.setAlignment(Paragraph.ALIGN_CENTER);
p2.setFont(paraFont2);
doc.add(p2);
/* Inserting Image in PDF */
/*ByteArrayOutputStream stream = new ByteArrayOutputStream();
Bitmap bitmap = BitmapFactory.decodeResource(getBaseContext().getResources(), R.drawable.android);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100 , stream);
Image myImg = Image.getInstance(stream.toByteArray());
myImg.setAlignment(Image.MIDDLE);
//add image to document
doc.add(myImg);*/
//set footer
Phrase footerText = new Phrase("This is an example of a footer");
HeaderFooter pdfFooter = new HeaderFooter(footerText, false);
doc.setFooter(pdfFooter);
Toast.makeText(getApplicationContext(), "Created...", Toast.LENGTH_LONG).show();
} catch (DocumentException de) {
Log.e("PDFCreator", "DocumentException:" + de);
} catch (IOException e) {
Log.e("PDFCreator", "ioException:" + e);
}
finally
{
doc.close();
}
}
void openPdf()
{
Intent intent = new Intent(Intent.ACTION_VIEW);
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/PDF";
File file = new File(path, "demo.pdf");
intent.setDataAndType( Uri.fromFile(file), "application/pdf" );
startActivity(intent);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
And this is the main activity.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<Button
android:id="#+id/button2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/textView1"
android:layout_marginTop="100dp"
android:text="Open PDF" />
<Button
android:id="#+id/button1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#+id/textView1"
android:layout_marginTop="44dp"
android:text="Generate PDF" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:text="#string/hello_world" />
Do it this way:
import com.cete.dynamicpdf.*;
import com.cete.dynamicpdf.pageelements.Label;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.widget.Toast;
public class DynamicPDFHelloWorld extends Activity {
private static String FILE = Environment.getExternalStorageDirectory()
+ "/HelloWorld.pdf";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Create a document and set it's properties
Document objDocument = new Document();
objDocument.setCreator("DynamicPDFHelloWorld.java");
objDocument.setAuthor("Your Name");
objDocument.setTitle("Hello World");
// Create a page to add to the document
Page objPage = new Page(PageSize.LETTER, PageOrientation.PORTRAIT,
54.0f);
// Create a Label to add to the page
String strText = "Hello World...\nFrom DynamicPDF Generator "
+ "for Java\nDynamicPDF.com";
Label objLabel = new Label(strText, 0, 0, 504, 100,
Font.getHelvetica(), 18, TextAlign.CENTER);
// Add label to page
objPage.getElements().add(objLabel);
// Add page to document
objDocument.getPages().add(objPage);
try {
// Outputs the document to file
objDocument.draw(FILE);
Toast.makeText(this, "File has been written to :" + FILE,
Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(this,
"Error, unable to write to file\n" + e.getMessage(),
Toast.LENGTH_LONG).show();
}
}
}
Also check these links. They will help you to fulfill your requirement.
http://www.dynamicpdf.com/Blog/post/2012/06/15/Generating-PDFs-Dynamically-on-Android.aspx
https://github.com/JoanZapata/android-pdfview
How to create PDFs in an Android app?
Render a PDF file using Java on Android
you'll find the correct code that actually works right.for creating a pdf file, putting some content in it, saving in and the opening the newly created file.
For this you'll need to add the jar of iTextG to your project:
OR
if you WANT TO convert your layout or view into pdf then you have to create image from your layout and then add into pdf.Perfect tutorial of that Go Through this Link . Hope this will help you guys.Thank you.
For Simple Create and Open pdf:
// Method for creating a pdf file from text, saving it then opening it for display
public void createandDisplayPdf(String text) {
Document doc = new Document();
try {
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/PDF";
File dir = new File(path);
if(!dir.exists())
dir.mkdirs();
File file = new File(dir, "mypdffile.pdf");
FileOutputStream fOut = new FileOutputStream(file);
PdfWriter.getInstance(doc, fOut);
//open the document
doc.open();
Paragraph p1 = new Paragraph(text);
Font paraFont= new Font(Font.FontFamily.COURIER);
p1.setAlignment(Paragraph.ALIGN_CENTER);
p1.setFont(paraFont);
//add paragraph to document
doc.add(p1);
} catch (DocumentException de) {
Log.e("PDFCreator", "DocumentException:" + de);
} catch (IOException e) {
Log.e("PDFCreator", "ioException:" + e);
}
finally {
doc.close();
}
viewPdf("mypdffile.pdf", "PDF");
}
// Method for opening a pdf file
private void viewPdf(String file, String directory) {
File pdfFile = new File(Environment.getExternalStorageDirectory() + "/" + directory + "/" + file);
Uri path = Uri.fromFile(pdfFile);
// Setting the intent for pdf reader
Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
pdfIntent.setDataAndType(path, "application/pdf");
pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
startActivity(pdfIntent);
} catch (ActivityNotFoundException e) {
Toast.makeText(this, "Can't read pdf file", Toast.LENGTH_SHORT).show();
}
}
Check this link,it requires you to download a jar file.(more description in the link).Here is a part of code to generate pdf.
package com.cete.androidexamples.dynamicpdf.helloworld;
import com.cete.dynamicpdf.*;
import com.cete.dynamicpdf.pageelements.Label;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.widget.Toast;
public class DynamicPDFHelloWorld extends Activity {
private static String FILE = Environment.getExternalStorageDirectory()
+ "/HelloWorld.pdf";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Create a document and set it's properties
Document objDocument = new Document();
objDocument.setCreator("DynamicPDFHelloWorld.java");
objDocument.setAuthor("Your Name");
objDocument.setTitle("Hello World");
// Create a page to add to the document
Page objPage = new Page(PageSize.LETTER, PageOrientation.PORTRAIT,
54.0f);
// Create a Label to add to the page
String strText = "Hello World...\nFrom DynamicPDF Generator "
+ "for Java\nDynamicPDF.com";
Label objLabel = new Label(strText, 0, 0, 504, 100,
Font.getHelvetica(), 18, TextAlign.CENTER);
// Add label to page
objPage.getElements().add(objLabel);
// Add page to document
objDocument.getPages().add(objPage);
try {
// Outputs the document to file
objDocument.draw(FILE);
Toast.makeText(this, "File has been written to :" + FILE,
Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(this,
"Error, unable to write to file\n" + e.getMessage(),
Toast.LENGTH_LONG).show();
}
}
}

exception determination how to know what to catch

I do understand the basics of try and catch in as much as you try some code and look for errors that occur and catch them and then do something based on the error. I have code that when run looks for a complete video file exists on the SD card it plays the video if it is not complete it downloads it to the SD card then I want it to play.
here is my code block
import java.io.BufferedInputStream;
import java.io.File;
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.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Window;
import android.widget.MediaController;
import android.widget.Toast;
import android.widget.VideoView;
public class VideoActivity extends Activity {
private static final String TAG = "MyActivity";
public static final int DIALOG_DOWNLOAD_PROGRESS = 0;
public static final Context ACTION_VIEW = null;
private ProgressDialog mProgressDialog;
public String url = "";
public String fName = "";
public String vidName = "";
public String path="";
//final VideoView videoView = (VideoView) findViewById(R.id.videoView1);
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
final String[] myAPP_FILES = getResources().getStringArray(R.array.APP_FILES);
final String[] myAPP_FILENAMES = getResources().getStringArray(R.array.APP_FILENAMES);
final String[] myAPP_NAMES = getResources().getStringArray(R.array.APP_NAMES);
final int[] myAPP_SIZES = getResources().getIntArray(R.array.APP_SIZES);
setContentView(R.layout.video);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
final VideoView videoView = (VideoView) findViewById(R.id.videoView1);
final MediaController mediaController = new MediaController(this);
mediaController.setAnchorView(videoView);
Bundle extras = getIntent().getExtras();
url = myAPP_FILES[extras.getInt("key") ];
fName = myAPP_FILENAMES[extras.getInt("key") ];
vidName = myAPP_NAMES[extras.getInt("key") ];
int fsize = (myAPP_SIZES[extras.getInt("key") ] -1 )*1000;
File file1 = new File(Environment.getExternalStorageDirectory(), fName );
if (file1.exists()) {
if(file1.length() < fsize) {
file1.delete();
}
}
loadMedia();
Toast.makeText(
getApplicationContext(),
"" + file1.length()+ " " + fsize,
Toast.LENGTH_LONG).show();
String pathfile = Environment.getExternalStorageDirectory() + "/" +fName;
try {
Uri video = Uri.parse(pathfile);
videoView.setMediaController(mediaController);
videoView.setVideoURI(video);
videoView.start();
} catch (Exception w) {}
}
private void loadMedia() {
//Check for media file download if not on sdcard
File file = new File(Environment.getExternalStorageDirectory(), fName );
if (!file.exists()) {
new DownloadFileAsync().execute(url);
}
}
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_DOWNLOAD_PROGRESS:
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage("Downloading to SD: " + vidName + "\n...Please allow download to finish completely...");
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(true);
mProgressDialog.show();
return mProgressDialog;
default:
return null;
}
}
class DownloadFileAsync extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialog(DIALOG_DOWNLOAD_PROGRESS);
}
#Override
protected String doInBackground(String... aurl) {
int count;
try {
URL url = new URL(aurl[0]);
URLConnection conexion = url.openConnection();
conexion.connect();
int lengthOfFile = conexion.getContentLength();
Log.d("ANDRO_ASYNC", "Length of file: " + lengthOfFile);
InputStream input = new BufferedInputStream(url.openStream(), 1024);
OutputStream output = new FileOutputStream("/sdcard/" + fName);
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress(""+(int)((total*100)/lengthOfFile));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {}
return null;
}
protected void onProgressUpdate(String... progress) {
Log.d("ANDRO_ASYNC",progress[0]);
mProgressDialog.setProgress(Integer.parseInt(progress[0]));
}
#Override
protected void onPostExecute(String unused) {
dismissDialog(DIALOG_DOWNLOAD_PROGRESS);
}
}
}
In operation a spinner is displayed and the user can select a video. It then checks to see if the file exists on the SD card if it is not it starts the download and a progress bar is displayed. Here is the problem At that time a message pops up that says:
CANNOT PLAY VIDEO
Sorry, this video cannot be played.
the download is progressing in the background and I can see the progress bar but it is darkened down
I do not want this message to appear.
I want to catch this and do nothing so the message will not appear
In the code I process the loadmedia function and then I set the video to play. I need to try and catch this step looking for this error message but I do not know what to look for
in my logcat I see this
02-02 09:35:29.257: W/MediaPlayer(13311): info/warning (1, 26)
02-02 09:35:29.257: E/MediaPlayer(13311): error (1, -4)
02-02 09:35:29.277: I/MediaPlayer(13311): Info (1,26)
02-02 09:35:29.277: E/MediaPlayer(13311): Error (1,-4)
02-02 09:35:29.277: D/VideoView(13311): Error: 1,-4
I think it is included here but I don't know how to translate this into a valid try and catch routine
Hopefully someone can help
To catch an exception an exception must be thrown. Looks like you're already catching the base level Exception which would catch any uncaught exception from the media player layer. Therefore, they're not throwing any that they aren't catching themselves.
So this isn't about catching exceptions at this point but registering to receive notification of errors that the framework provides. Looking here shows a way to register a listener for errors. Whether that means that the error won't show up as you've described is unknown. I suspect it'll still show. But you may have no control over that.

How can I look at the database of my application on a non-rooted phone

I have installed my android application (with debug on) on my non-rooted Nexus phone.
My question is how can I look at the database created by my application?
Thank you.
you cannot do that but if its your own application you can actually go through the tedious way of exporting your database files to the sd card heres a utility method I came out with to help with that..
Change the string "/data/net.rejinderi.yourpackagehere/databases/yourdbnamehere.db" to fit your application, create an instance of the AsyncTask and call execute on it. that simple.
Be sure to include the permissions of using the external storage though..
Good luck. :)
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Environment;
import android.widget.Toast;
public class ExportDatabaseFileTask extends AsyncTask<Void, Void, Boolean> {
private final ProgressDialog progressDialog;
private Context context;
public ExportDatabaseFileTask(Context context)
{
this.context = context;
progressDialog = new ProgressDialog(context);
}
protected void onPreExecute() {
this.progressDialog.setMessage("Exporting database...");
this.progressDialog.show();
}
protected Boolean doInBackground(Void... args) {
File dbFile = new File(Environment.getDataDirectory() + "/data/net.rejinderi.yourpackagehere/databases/yourdbnamehere.db");
File exportDir = new File(Environment.getExternalStorageDirectory(), "");
if (!exportDir.exists()) {
exportDir.mkdirs();
}
File file = new File(exportDir, dbFile.getName());
try {
file.createNewFile();
this.copyFile(dbFile, file);
return true;
} catch (IOException e) {
return false;
}
}
protected void onPostExecute(final Boolean success) {
if (this.progressDialog.isShowing()) {
this.progressDialog.dismiss();
}
if (success) {
Toast.makeText(context, "Export successful!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "Export failed", Toast.LENGTH_SHORT).show();
}
}
void copyFile(File src, File dst) throws IOException {
FileChannel inChannel = new FileInputStream(src).getChannel();
FileChannel outChannel = new FileOutputStream(dst).getChannel();
try {
inChannel.transferTo(0, inChannel.size(), outChannel);
} finally {
if (inChannel != null)
inChannel.close();
if (outChannel != null)
outChannel.close();
}
}
}
I've looked into this and unfortunately there's no practical way to do this. This is because you can't get access to the files on a non-rooted phone.
This is why whenever I need to access the database, i just fire up the emulator since you can easily get access to the database and even make changes on the fly and see how it effects the app.
for debug purposes you can programatically copy db file(s) from internal phone memory to external (SD card). they're just a files after all

Android UNZIP Inputstream problem

I am trying to unzip a file located on SDCARD of Android device.
If the ZIP file only contains files NOT FOLDERS everything is fine. However the production file that I want the app to unzip contains multiple directories and sub-directories. This is where I run into issues.
The code isnt creating the folder structure required. If I manually create the folders prior to running the class it unzips as planned, but in the future I wont know the directory structure and need the code to create the proper folder structure.
Here is the code I'm working with
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;
public class HomeActivity extends Activity
{
private TextView tv;
private static final String ROOT_FOLDER = Environment.getExternalStorageDirectory()
+ File.separator + "FacebookPhotos";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv = (TextView) findViewById(R.id.tv);
tv.append("Reading zip file from assets folder...");
// Start the unzipping process
thread.start();
}
private Thread thread = new Thread()
{
#Override
public void run()
{
sendMessage("-----------------------------------------------");
// Create a directory in the SDCard to store the files
File file = new File(ROOT_FOLDER);
if (!file.exists())
{
file.mkdirs();
}
else
{
file.delete();
}
try
{
// Open the ZipInputStream
ZipInputStream inputStream = new ZipInputStream(new FileInputStream("/sdcard/Photos/photos.zip"));
// Loop through all the files and folders
for (ZipEntry entry = inputStream.getNextEntry(); entry != null; entry = inputStream
.getNextEntry())
{
sendMessage("Extracting: " + entry.getName() + "...");
String innerFileName = ROOT_FOLDER + File.separator + entry.getName();
File innerFile = new File(innerFileName);
if (innerFile.exists())
{
innerFile.delete();
}
// Check if it is a folder
if (entry.isDirectory())
{
// Its a folder, create that folder
innerFile.mkdirs();
}
else
{
// Create a file output stream
FileOutputStream outputStream = new FileOutputStream(innerFileName);
final int BUFFER = 2048;
// Buffer the output to the file
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream,
BUFFER);
// Write the contents
int count = 0;
byte[] data = new byte[BUFFER];
while ((count = inputStream.read(data, 0, BUFFER)) != -1)
{
bufferedOutputStream.write(data, 0, count);
}
// Flush and close the buffers
bufferedOutputStream.flush();
bufferedOutputStream.close();
}
sendMessage("DONE");
// Close the current entry
inputStream.closeEntry();
}
inputStream.close();
sendMessage("-----------------------------------------------");
sendMessage("Unzipping complete");
}
catch (IOException e)
{
sendMessage("Exception occured: " + e.getMessage());
e.printStackTrace();
}
}
};
private Handler handler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
tv.append("\n" + msg.getData().getString("data"));
super.handleMessage(msg);
}
};
private void sendMessage(String text)
{
Message message = new Message();
Bundle data = new Bundle();
data.putString("data", text);
message.setData(data);
handler.sendMessage(message);
}
}
Check out this answer
Android - Unzip a folder?
I think sometimes in ZIP files, the directory entries may be added after their files. In this case, you won't get the directory before the file. The linked example calls file.getParentFile().exists() for regular files and creates that directory if it doesn't eixst.

Categories

Resources