I am writing an Android application to display pdf files on the device. And I need to use the current versioncode (35498) of the Adobe Reader to display the pdf files.I have with code to display list of files on the screen. Now I need to invoke the Adobe reader (not any other pdf reader installed on the device) onclick of each document. I am not sure how I code that. I am an Android newbie. Any help will be greatly appreciated.
Thanks in Advance,
Navin
I see that you want to open Adobe specifically, but you may want to consider doing it the more Android-like way of opening a general intent and allowing the user to choose how it opens. For your reference, you'd do that with the following code:
private void openFile(File f, String mimeType)
{
Intent viewIntent = new Intent();
viewIntent.setAction(Intent.ACTION_VIEW);
viewIntent.setDataAndType(Uri.fromFile(file), mimeType);
// using the packagemanager to query is faster than trying startActivity
// and catching the activity not found exception, which causes a stack unwind.
List<ResolveInfo> resolved = getPackageManager().queryIntentActivities(viewIntent, 0);
if(resolved != null && resolved.size() > 0)
{
startActivity(viewIntent);
}
else
{
// notify the user they can't open it.
}
}
If you really need to use both Abode Reader specifically, and a specific version, you would need to query for it using PackageManager.getPackageInfo(String, int)
Try the following code
private void loadDocInReader(String doc)
throws ActivityNotFoundException, Exception {
try {
Intent intent = new Intent();
intent.setPackage("com.adobe.reader");
intent.setDataAndType(Uri.parse(doc), "application/pdf");
startActivity(intent);
} catch (ActivityNotFoundException activityNotFoundException) {
activityNotFoundException.printStackTrace();
throw activityNotFoundException;
} catch (Exception otherException) {
otherException.printStackTrace();
throw otherException;
}
}
If you are in "online mode", here is an interesting alternate solution using Google docs.
String myPDFURL = "http://{link of your pdf file}";
String link;
try {
link = "http://docs.google.com/viewer?url="
+ URLEncoder.encode(myPDFURL, "UTF-8")
+ "&embedded=true";
} catch (Exception e) {
e.printStackTrace();
}
Uri uri = Uri.parse(link);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
This works, setDataAndType method cannot seem to correctly recognize the PDF type if used via URL.
private static Intent newPDFLinkIntent(String url) {
Uri pdfURL = Uri.parse(url);
Intent pdfDownloadIntent = new Intent(Intent.ACTION_VIEW, pdfURL);
pdfDownloadIntent.setType("application/pdf");
pdfDownloadIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
return pdfDownloadIntent ;
}
Unfortunately, the PDF applications I'm using don't anticipate downloading and caching the online content (some will have memory leak error, some will reject link downloading), so you'll eventually end up invoking an intent that downloads the PDF first, before opening the downloaded content via the notification link. I eventually used the solution below:
private static Intent newPDFLinkIntent(String url) {
Intent pdfDownloadIntent = null;
try {
pdfDownloadIntent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
pdfDownloadIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
} catch (URISyntaxException e) {
Log.e("PDF Link Tag", e.getMessage());
}
return pdfDownloadIntent;
}
Related
Im trying to save a pdf file on a user-picked location but Im having problems passing data through the intent.
I tried using a bundle to pass the info but it is always null.
It only works if I add a local variable and assign it in the #save method. But I want to pass it through the intent.
The thing is im not going into another activity, just to choose a directory and im coming back.
`protected void save(byte[] bytes, String fileName, String mimeType) {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.setType(mimeType);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.putExtra(Intent.EXTRA_TITLE, fileName);
intent.putExtra("bytes", bytes);
activityResultLaunch.launch(intent);
}`
`ActivityResultLauncher<Intent> activityResultLaunch = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
Intent data = result.getData();
try {
Uri uri = data.getData();
OutputStream outputStream = getContext().getContentResolver().openOutputStream(uri);
// here it is always null
//byte[] bytes = data.getByteArrayExtra("bytes");
outputStream.write(bytes);
outputStream.close();
Toast.makeText(getContext(), "Successfully saved document to device!", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Toast.makeText(getContext(), "Failed to save document to device.", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
});`
Any suggestions? I dont see what im missing here, ive been banging my head on this for a couple of hours and couldnt get it to work. Any help is greatly appreciated!
intent.putExtra("bytes", bytes);
Here, you are passing an Intent extra to the activity that you are starting. That activity is a device-supplied activity that responds to ACTION_CREATE_DOCUMENT.
More importantly, it is not your activity. It is certainly not the activity that is calling launch() for that Intent.
So, that bytes extra will be available to the ACTION_OPEN_DOCUMENT activity. That activity will ignore that extra. It will not include that extra in the completely different Intent that is delivered to your onActivityResult() method.
But I want to pass it through the intent.
That is not an option in Android, sorry.
I have put a pdf file inside my app raw/my_pdf.pdf to prevent to be copied and want to open it with external app in my tablet
here is what I tried :
public void loadDocInReader(View v)
throws ActivityNotFoundException, Exception {
try {
Intent intent = new Intent();
intent.setPackage("com.foobnix.pro.pdf.reader");
intent.setDataAndType(Uri.parse("raw/my_pdf.pdf"), "application/pdf");
startActivity(intent);
} catch (ActivityNotFoundException activityNotFoundException) {
activityNotFoundException.printStackTrace();
throw activityNotFoundException;
} catch (Exception otherException) {
otherException.printStackTrace();
throw otherException;
}
}
this method launch the external app I want but with no pdf file just a blank page
also I know that it is possible to get it as inputstream :
InputStream raw = getResources().openRawResource(R.raw.my_pdf)
but how to open it with my specified app
is there any way to fix that
I'm struggling with the same problem. I found that you need to set up a content provider that exposes some of your files / folders to be accessed by other apps.
Usually, android apps have their files enclosed into a sandbox that's not accessible from other apps installed on your system (some clever way to address security issues). So you need to expose them via a content provider.
Try this:
https://vshivam.wordpress.com/2015/06/30/storing-files-privately-on-android-and-opening-them-using-an-external-application/
I'm implementing it tonight... wish you luck!
Below code will determine whether a suitable application exists on the user's device, without catching exceptions. And if exist it will open pdf file with suitable app.
Intent intent = new Intent(Intent.ACTION_VIEW,
Uri.parse("path-to-document"));
intent.setType("application/pdf");
PackageManager pm = getPackageManager();
List<ResolveInfo> activities = pm.queryIntentActivities(intent, 0);
if (activities.size() > 0) {
startActivity(intent);
} else {
// Do something else here. Maybe pop up a Dialog or Toast
}
I use the following snippet to open or share any file from device's storage (MyFile is my own class which extends File and should be considered as File. The flag String I'm passing is either Intent.ACTION_VIEW or Intent_ACTION_SEND):
public void openOrShare(String flag, MyFile f){
try {
MimeTypeMap mmap = MimeTypeMap.getSingleton();
String type = MimeTypeMap.getFileExtensionFromUrl(f
.getName());
String ftype = mmap.getMimeTypeFromExtension(type);
if (ftype == null)
ftype = "*/*";
Intent intent = new Intent(flag);
Uri data = Uri.fromFile(f);
intent.setDataAndType(data, ftype);
startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
Tools.gimmeToast(
getActivity(),
"no application found to handle this file type",
Toast.LENGTH_LONG);
} catch (Exception e) {
e.printStackTrace();
}
}
While passing Intent.ACTION_VIEW everything works fine for any (also custom) types, the system creates a chooser and lists the apps, for well-known files it launches the correct Activity to handle the file immediately .
The problem: passing Intent.ACTION_SEND seems to be working halfway - it creates the chooser as well, however most apps (Dropbox and many more that I've tested with) just crash with an NPE when confirming the action. Testing with various email clients also failed: they don't crash like most of the other apps, but create a message and put the local Uri (like //storage/.....) in the To field (gmail) OR simply create a new empty message, ignoring the Intent data (yahoo! mail), while I expect them to attach the file to a new message.
The question: what am I doing wrong to share any file type?
EDIT
I figured out that it works if using intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f));, however there's an ActivityNotFoundException being caught when trying to share some specific files (like .dat). As far as I know, apps like Dropbox support adding any file types. Looking for a workaround.
If you don't know the MIME Type of the file, then do not set it.
So I would try:
Intent intent = new Intent(flag);
Uri data = Uri.fromFile(f);
String ftype = mmap.getMimeTypeFromExtension(type);
if (ftype != null) {
intent.setDataAndType(data, ftype);
} else {
intent.setData(data);
}
setDataAndType needs data and explicit mime type (maybe */* is not).
Never mind, I finally figured that out. So here's the working solution which allows to share any type of data using any app*:
*Note: the below code actually also lists apps that might be not able to handle specific file types, those apps (at least they should) notify the user that the file type is not supported if this is the case
public void doShare(MyFile f) {
try {
Intent intent = new Intent(Intent.ACTION_SEND);
MimeTypeMap mmap = MimeTypeMap.getSingleton();
String type = MimeTypeMap.getFileExtensionFromUrl(f.getName());
String ftype = mmap.getMimeTypeFromExtension(type);
if (ftype == null)
ftype = "*/*";
intent.setType(ftype);
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f));
startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
Tools.gimmeToast(getActivity(),
"no application found to handle this file type",
Toast.LENGTH_LONG);
} catch (Exception e) {
e.printStackTrace();
}
}
I'm new in android development so I know how to open pdf from assest folder file by using some of the available API .
But how can I make for any pdf means like adobe reader.
If you would like to open Adobe Reader (with a version) specifically from your app, you need to query it using PackageManager.getPackageInfo(String, int)!
You can also try the following code,
private void loadDocInAdobeReader(String someDoc)
throws ActivityNotFoundException, Exception {
try {
Intent intent = new Intent();
intent.setPackage("com.adobe.reader");
intent.setDataAndType(Uri.parse(someDoc), "application/pdf");
startActivity(intent);
} catch (ActivityNotFoundException ae) {
ae.printStackTrace();
throw ae;
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
I have written a piece of code that detects installed application in android and opens the file with the application.For example, a word document should be opened with some office apk.
Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
Uri data = Uri.fromFile(temp_file);
String type = getMimeType(temp_file.getName());
intent.setDataAndType(data, type);
this.startActivity(intent);
In the above code temp_file is the file that should be opened.And below is the generalised code that I wrote to get the MIME type
public static String getMimeType(String url) {
String type = null;
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
if (extension != null) {
MimeTypeMap mime = MimeTypeMap.getSingleton();
type = mime.getMimeTypeFromExtension(extension);
}
return type;
}
But when I execute ,it throws android.content.ActivityNotFoundException exception.So,am I doing anything wrong here?
You are calling getMimeType() and passing it the file name. But your method getMimeType() expects an URL. The documentation for MimeTypeMap.getFileExtensionFromUrl() specifically says:
This method is a convenience method for obtaining the extension of a url and has undefined results for other Strings.
You are probably getting null for the mime type. Add some debug logging and check what getMimeType() is returning.
Also, look in the logcat. It should tell you the content of the Intent it is trying to resolve. That should also give you a hint.
This may help you,
private void readFile(File file){
Uri path = Uri.fromFile(file);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(path, "application/pdf");// for .pdf file
//intent.setDataAndType(path, "application/msword");// for msword file
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
startActivity(intent);
}
catch (ActivityNotFoundException e) {
String str= "No Application Available to View .pdf file.";
showToast(str);
}
where file is the name of file to be open
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
File file=new File("/sdcard/yourfile");
if(file.exists())
{
Uri path=Uri.fromFile(file);
Intent intent=new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(path, "application/readername");
try
{
startActivity(intent);
}
catch(ActivityNotFoundException e)
{
Toast.makeText(TestActivity.this, "No software for PDF", Toast.LENGTH_SHORT).show();
}
}
}
});