android and itext - android

I want to display pdf in android with next/previous and zoom effect,i check out the already exits the lib for that but it is too slow then, I move to itext.
I install the jar file and code to get the total number pages.
But question how i can display the pdf,i mean to say take the text view,then how i will manage the background of the pdf,so there are many query.
Can anybody help me out if some-one have gone through the steps
Thanks in advance and every suggestion wel come here.

As far as I know iText is not meant to display PDF files, but to manipulate (as in: read, change, write) them. Viewing is not possible.

try it:
private void openFile(String path) {
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(android.content.Intent.ACTION_VIEW);
File f = new File(path);
String type = FileUtil.getMIMEType(f.getName());
intent.setDataAndType(Uri.fromFile(f), type);
startActivity(intent);
}
public static String getMIMEType(String name) {
String type = "";
String end = name.substring(name.lastIndexOf(".") + 1, name.length()).toLowerCase();
end = end.toLowerCase();
if (end.equals("apk")) {
return "application/vnd.android.package-archive";
} else if (end.equals("mp4") || end.equals("avi") || end.equals("3gp")
|| end.equals("rmvb")) {
type = "video";
} else if (end.equals("m4a") || end.equals("mp3") || end.equals("mid") || end.equals("xmf")
|| end.equals("ogg") || end.equals("wav")) {
type = "audio";
} else if (end.equals("jpg") || end.equals("gif") || end.equals("png")
|| end.equals("jpeg") || end.equals("bmp")) {
type = "image";
} else if (end.equals("txt") || end.equals("log") || end.equals("sql")) {
type = "text";
}else {
type = "*";
}
type += "/*";
return type;
}

Install a pdf viewer such as Adobe Reader onto your device (it is available onn Android MarketPlace). Then from use this function in your app you can use an intent to open the pdf
public void OpenPDF(File f)
{
Uri uri = Uri.parse("file://" + file.getAbsolutePath());
intent.setDataAndType(uri, "application/pdf");
startActivity(intent);
}

Related

Is it possible to know if a document is opened/viewed by user in xamarin android app?

I need to check if a document (pdf,xls,docx,ppt..etc) is viewed by user or not. In some user's devices there are no apps to open some document types. In such cases I need to know that the document is not opened/viewed by user.
This is an android app developed using xamarin forms. Used below code to open document. This is working fine if there is an app to open respective document. But, if there are no apps to open the document it shows blank activity with the title "Choose an Application:"
...other code here...
var chooserIntent = Intent.CreateChooser(intent, "Choose an Application:");
activity.StartActivityForResult(chooserIntent, 10);
You can check it by the Android file MIME type.Refer the following code
Dictionary<string, string> matchArray = new Dictionary<string, string>();
matchArray.Add(".3gp", "video/3gpp");
matchArray.Add(".apk", "application/vnd.android.package-archive");
matchArray.Add(".doc", "application/msword");
matchArray.Add(".gif", "image/gif");
matchArray.Add(".wps", "application/vnd.ms-works");
matchArray.Add(".pdf", "application/pdf");
matchArray.Add(".ppt", "application/vnd.ms-powerpoint");
matchArray.Add(".png", "image/png");
//...
public void OpenFileByPath(Context context, string path)
{
if (context == null || path == null)
return;
string type = "";
foreach (string key in matchArray.Keys)
{
if (path.Contains(key))
{
type = matchArray[key];
break;
}
}
if (type == "")
{
//there is no app can open the file ,do some you want
}
else
{
// open your file
}
}
You can add more key-values about MIME type by searching from the internet

Android 5.0 DocumentFile from tree URI

Alright, I've searched and searched and no one has my exact answer, or I missed it. I'm having my users select a directory by:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, READ_REQUEST_CODE);
In my activity I want to capture the actual path, which seems to be impossible.
protected void onActivityResult(int requestCode, int resultCode, Intent intent){
super.onActivityResult(requestCode, resultCode, intent);
if (resultCode == RESULT_OK) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M){
//Marshmallow
} else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){
//Set directory as default in preferences
Uri treeUri = intent.getData();
//grant write permissions
getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
//File myFile = new File(uri.getPath());
DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
The folder I selected is at:
Device storage/test/
I've tried all of the following ways to get an exact path name, but to no avail.
File myFile = new File (uri.getPath());
//returns: /tree/1AF6-3708:test
treeUri.getPath();
//returns: /tree/1AF6-3708:test/
pickedDir.getName()
//returns: test
pickedDir.getParentFile()
//returns: null
Basically I need to turn /tree/1AF6-3708: into /storage/emulated/0/ or whatever each device calls it's storage location. All other available options return /tree/1AF6-37u08: also.
There are 2 reasons I want to do it this way.
1) In my app I store the file location as a shared preference because it is user specific. I have quite a bit of data that will be downloaded and stored and I want the user to be able to place it where they want, especially if they have an additional storage location. I do set a default, but I want versatility, rather than the dedicated location of:
Device storage/Android/data/com.app.name/
2) In 5.0 I want to enable the user to get read/write permissions to that folder and this seems the only way to do that. If I can get read/write permissions from a string that would fix this issue.
All solutions I've been able to find relate to Mediastore, which doesn't help me exactly. I have to be missing something somewhere or I must have glazed over it. Any help would be appreciated. Thanks.
This will give you the actual path of the selected folder It will work ONLY for files/folders that belong in local storage.
Uri treeUri = data.getData();
String path = FileUtil.getFullPathFromTreeUri(treeUri,this);
where FileUtil is the following class
public final class FileUtil {
private static final String PRIMARY_VOLUME_NAME = "primary";
#Nullable
public static String getFullPathFromTreeUri(#Nullable final Uri treeUri, Context con) {
if (treeUri == null) return null;
String volumePath = getVolumePath(getVolumeIdFromTreeUri(treeUri),con);
if (volumePath == null) return File.separator;
if (volumePath.endsWith(File.separator))
volumePath = volumePath.substring(0, volumePath.length() - 1);
String documentPath = getDocumentPathFromTreeUri(treeUri);
if (documentPath.endsWith(File.separator))
documentPath = documentPath.substring(0, documentPath.length() - 1);
if (documentPath.length() > 0) {
if (documentPath.startsWith(File.separator))
return volumePath + documentPath;
else
return volumePath + File.separator + documentPath;
}
else return volumePath;
}
private static String getVolumePath(final String volumeId, Context context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
return null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
return getVolumePathForAndroid11AndAbove(volumeId, context);
else
return getVolumePathBeforeAndroid11(volumeId, context);
}
private static String getVolumePathBeforeAndroid11(final String volumeId, Context context){
try {
StorageManager mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
Class<?> storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");
Method getVolumeList = mStorageManager.getClass().getMethod("getVolumeList");
Method getUuid = storageVolumeClazz.getMethod("getUuid");
Method getPath = storageVolumeClazz.getMethod("getPath");
Method isPrimary = storageVolumeClazz.getMethod("isPrimary");
Object result = getVolumeList.invoke(mStorageManager);
final int length = Array.getLength(result);
for (int i = 0; i < length; i++) {
Object storageVolumeElement = Array.get(result, i);
String uuid = (String) getUuid.invoke(storageVolumeElement);
Boolean primary = (Boolean) isPrimary.invoke(storageVolumeElement);
if (primary && PRIMARY_VOLUME_NAME.equals(volumeId)) // primary volume?
return (String) getPath.invoke(storageVolumeElement);
if (uuid != null && uuid.equals(volumeId)) // other volumes?
return (String) getPath.invoke(storageVolumeElement);
}
// not found.
return null;
} catch (Exception ex) {
return null;
}
}
#TargetApi(Build.VERSION_CODES.R)
private static String getVolumePathForAndroid11AndAbove(final String volumeId, Context context) {
try {
StorageManager mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
List<StorageVolume> storageVolumes = mStorageManager.getStorageVolumes();
for (StorageVolume storageVolume : storageVolumes) {
// primary volume?
if (storageVolume.isPrimary() && PRIMARY_VOLUME_NAME.equals(volumeId))
return storageVolume.getDirectory().getPath();
// other volumes?
String uuid = storageVolume.getUuid();
if (uuid != null && uuid.equals(volumeId))
return storageVolume.getDirectory().getPath();
}
// not found.
return null;
} catch (Exception ex) {
return null;
}
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static String getVolumeIdFromTreeUri(final Uri treeUri) {
final String docId = DocumentsContract.getTreeDocumentId(treeUri);
final String[] split = docId.split(":");
if (split.length > 0) return split[0];
else return null;
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static String getDocumentPathFromTreeUri(final Uri treeUri) {
final String docId = DocumentsContract.getTreeDocumentId(treeUri);
final String[] split = docId.split(":");
if ((split.length >= 2) && (split[1] != null)) return split[1];
else return File.separator;
}
}
UPDATE:
To address the Downloads issue mentioned in the comments: If you select Downloads from the left drawer in the default Android file picker you are not actually selecting a directory. Downloads is a provider. A normal folder tree uri looks something like this:
content://com.android.externalstorage.documents/tree/primary%3ADCIM
The tree uri of Downloads is
content://com.android.providers.downloads.documents/tree/downloads
You can see that the one says externalstorage while the other one says providers. That is why it cannot be matched to a directory in the file system. Because it is not a directory.
SOLUTION: You can add an equality check and if the tree uri is equal to that then return the default download folder path which can be retrieved like this:
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
And do something similar for all the providers if you wish to. And it would work correctly most of the time I assume. But I imagine that there are edge cases where it wouldn't.
thanx to #DuhVir for supporting the Android R case
In my activity I want to capture the actual path, which seems to be impossible.
That's is because there may not be an actual path, let alone one you can access. There are many possible document providers, few of which will have all their documents locally on the device, and few of those that do will have the files on external storage, where you can work with them.
I have quite a bit of data that will be downloaded and stored and I want the user to be able to place it where they want
Then use the Storage Access Framework APIs, rather than thinking that documents/trees that you get from the Storage Access Framework are always local. Or, do not use ACTION_OPEN_DOCUMENT_TREE.
In 5.0 I want to enable the user to get read/write permissions to that folder
That is handled by the storage provider, as part of how the user interacts with that storage provider. You are not involved.
It's addition to #Anonymous answer for Android 11.
#TargetApi(Build.VERSION_CODES.R)
private static String getVolumePath_SDK30(final String volumeId, Context context) {
try {
StorageManager mStorageManager =
(StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
if (mStorageManager == null) return null;
List<StorageVolume> storageVolumes = mStorageManager.getStorageVolumes();
for (StorageVolume storageVolume : storageVolumes) {
String uuid = storageVolume.getUuid();
Boolean primary = storageVolume.isPrimary();
if (primary == null) return null;
// primary volume?
if (primary && PRIMARY_VOLUME_NAME.equals(volumeId))
return storageVolume.getDirectory().getPath();
// other volumes?
if (uuid != null && uuid.equals(volumeId))
return storageVolume.getDirectory().getPath();
}
// not found.
return null;
} catch (Exception ex) {
return null;
}
}
I was trying to add a default save directory before or if user does not select a custom directory using SAF UI in preferences screen of my app. It's possible for users to miss selecting a folder and app may crash. To add a default folder in device memory you should
DocumentFile saveDir = null;
saveDir = DocumentFile.fromFile(Environment.getExternalStorageDirectory());
String uriString = saveDir.getUri().toString();
List<UriPermission> perms = getContentResolver().getPersistedUriPermissions();
for (UriPermission p : perms) {
if (p.getUri().toString().equals(uriString) && p.isWritePermission()) {
canWrite = true;
break;
}
}
// Permitted to create a direct child of parent directory
DocumentFile newDir = null;
if (canWrite) {
newDir = saveDir.createDirectory("MyFolder");
}
if (newDir != null && newDir.exists()) {
return newDir;
}
This snippet will create a directory inside main memory of device and grant read/write permissions for that folder and sub-folders. You can't directly create MyFolder/MySubFolder hierarchy, you should create another directory again.
You can check if that directory has permission to write, as far i seen on 3 devices, it returns true if it's created using DocumentFileinstead of File class. This is a simple method for creating and granting write permission for Android >= 5.0 without using ACTION_OPEN_DOCUMENT_TREE
public static String findFullPath(String path) {
String actualResult="";
path=path.substring(5);
int index=0;
StringBuilder result = new StringBuilder("/storage");
for (int i = 0; i < path.length(); i++) {
if (path.charAt(i) != ':') {
result.append(path.charAt(i));
} else {
index = ++i;
result.append('/');
break;
}
}
for (int i = index; i < path.length(); i++) {
result.append(path.charAt(i));
}
if (result.substring(9, 16).equalsIgnoreCase("primary")) {
actualResult = result.substring(0, 8) + "/emulated/0/" + result.substring(17);
} else {
actualResult = result.toString();
}
return actualResult;
}
this function gives me the absolute path from tree uri.
this solution working on most of device i tested in more than 1000 devices.
it also gives us the right absolute path of folder which contained in memory card or OTG.
How it Works?
basically most of devices have the path that starts with /Storage/ prefix. and the middle part of path contains mounted point name i.e /emulated/0/ for internal Storage, or some string like /C0V54440/ etc (just example). and the last segment is path from root of storage to folder like /movie/piratesofthecarribian
so, the path we constructed from :- /tree/primary:movie/piratesofthecarribian is :- /storage/emulated/0/movie/piratesofthecarribian
You can find more information on my github repo. visit there to get the android code about how to convert tree uri to actual absolute path.
gihub(https://github.com/chetanborase/TreeUritoAbsolutePath)
public static String findFullPath(String path) {
String actualResult="";
path=path.substring(5);
int index=0;
StringBuilder result = new StringBuilder("/storage");
for (int i = 0; i < path.length(); i++) {
if (path.charAt(i) != ':') {
result.append(path.charAt(i));
} else {
index = ++i;
result.append('/');
break;
}
}
for (int i = index; i < path.length(); i++) {
result.append(path.charAt(i));
}
if (result.substring(9, 16).equalsIgnoreCase("primary")) {
actualResult = result.substring(0, 8) + "/emulated/0/" + result.substring(17);
} else {
actualResult = result.toString();
}
return actualResult;
}

Read file of any extension in android programmatically

Just want to confirm that is it possible that when i click on file of any extension will open up with its compatible software in android phone or display me the list of software’s present in mobile which can open the file and if it didn't found any software it will indicate user to first download the software to open that particular file (All this thing need to be done pro grammatically).
Thanks.
Any help will be appreciated.
In order to open the file you can use the following method, If there is no application that can handle given file, it simply shows a Toast saying no application found.
private void viewFile(String filePath, String title, int fileType) {
Uri uri = Uri.parse("file://" + filePath);
Intent intent = new Intent(Intent.ACTION_VIEW);
String dataAndType = getIntentDataAndType(filePath);
intent.setDataAndType(uri, dataAndType);
intent.putExtra(Intent.EXTRA_TITLE, title);
// Verify that the intent will resolve to an activity
if (intent.resolveActivity(getActivity().getPackageManager()) != null) {
startActivity(intent);
} else {
Toast.makeText(getActivity(), "No Application found", Toast.LENGTH_SHORT).show();
}
}
UPDATED :
For finding the mime type of the file.
private String getIntentDataAndType(String filePath) {
String exten = "";
int i = filePath.lastIndexOf('.');
// If the index position is greater than zero then get the substring.
if (i > 0) {
exten = filePath.substring(i + 1);
}
String mimeType = android.webkit.MimeTypeMap.getSingleton().getMimeTypeFromExtension(exten);
mimeType = (mimeType == null) ? "*/*" : mimeType;
return mimeType;
}

Open files from own file explorer

I've coded my own file explorer and now I want to start to Implement capabilities to open various files. I have implemented Mime Types and all other things but how can I parse specific selected file to specific "viewer activity"? I know by using intents but how to receive it in that viewer app and use it. Many thanks guys :)
Something like this should work. Change file to whatever you want.
File file = new File(Environment.getExternalStorageDirectory(), "movie.mp4");
int index = file.getName().lastIndexOf(".") + 1;
String extension = null;
if (index > 0) {
extension = file.getName().substring(index);
}
Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
Uri u = Uri.parse("file://" + file.getAbsolutePath());
String mimeType = null;
if (extension != null) {
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
if (mimeType == null) {
mimeType = "*/*";
}
intent.setDataAndType(u, mimeType);
try {
startActivity(Intent.createChooser(intent, "Open with..."));
} catch (ActivityNotFoundException e) {
// handle the exception
}

How to open all any fomat files on Android

I try to implement a browser-like app.
I want to let it can open any format files which supported by device.
I know below code can open specific format:
String mimetype = mime_type(FileName);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(File), mimetype);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
public String mime_type(String name) {
String type = null;
String[] mime = {".htm\ttext/html", ".html\ttext/html", ".doc\tapplication/msword", ".ppt\tapplication/vnd.ms-powerpoint", ".xls\tapplication/vnd.ms-excel",
".txt\ttext/plain", ".pdf\tapplication/pdf", ".xlsx\tapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
".pptx\tapplication/vnd.openxmlformats-officedocument.presentationml.presentation", ".docx\tapplication/vnd.openxmlformats-officedocument.wordprocessingml.document"};
int i;
for(i = 0; i < mime.length; i++) {
if(name.toLowerCase().endsWith(mime[i].split("\t")[0])) {
return mime[i].split("\t")[1];
}
}
return type;
}
But the file formats are more than I can list.
If any methods to do it for all formats?
Or any methods to list all applications let user select?
I find set mimetype to */* can arrive it.
It will show all intalled app for select.

Categories

Resources