package com.odoo.base.ir;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.os.Parcelable;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.provider.OpenableColumns;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.Builder;
import android.util.Base64;
import android.util.Log;
import android.webkit.MimeTypeMap;
import android.widget.Toast;
import com.odoo.App;
import com.odoo.orm.OColumn;
import com.odoo.orm.ODataRow;
import com.odoo.orm.OValues;
import com.odoo.util.Base64Helper;
import com.odoo.util.ODate;
import com.odoo.R;
public class Attachments implements OnClickListener {
public static final String TAG = Attachments.class.getSimpleName();
public static final String KEY_DB_DATAS = "db_datas";
public static final String KEY_TYPE = "type";
public static final int REQUEST_CAMERA = 111;
public static final int REQUEST_IMAGE = 112;
public static final int REQUEST_AUDIO = 113;
public static final int REQUEST_FILE = 114;
private static final int SINGLE_ATTACHMENT_STREAM = 115;
private String KEY_FILE_URI = "file_uri";
private String KEY_FILE_NAME = "datas_fname";
private String KEY_FILE_TYPE = "file_type";
private Context mContext = null;
private App mApp = null;
private IrAttachment mAttachment = null;
private Notification mNotification = null;
private Builder mNotificationBuilder = null;
private PendingIntent mNotificationResultIntent = null;
private NotificationManager mNotificationManager = null;
private static Integer notification_id = 1;
private String[] mOptions = null;
private Uri newImageUri;
public enum Types {
CAPTURE_IMAGE, IMAGE, IMAGE_OR_CAPTURE_IMAGE, AUDIO, FILE, OTHER
}
private Types mDialogType = null;
public Attachments(Context context) {
mContext = context;
mApp = (App) mContext.getApplicationContext();
mAttachment = new IrAttachment(mContext);
}
public void downloadAttachment(int attachment_id) {
ODataRow attachment = mAttachment.select(attachment_id);
if (attachment != null) {
String uri = attachment.getString(KEY_FILE_URI);
if (uri.equals("false")) {
_download(attachment);
} else {
Uri file_uri = Uri.parse(uri);
if (fileExists(file_uri)) {
_open(file_uri);
} else if (isKitKat()) {
String kitkatDoc = getKitKatDocPath(file_uri);
if (kitkatDoc != null) {
file_uri = Uri.fromFile(new File(kitkatDoc));
_open(file_uri);
} else if (attachment.getInt("id") != 0)
_download(attachment);
else
noFileFound();
} else {
noFileFound();
}
}
} else {
noFileFound();
}
}
private void _open(Uri uri) {
requestIntent(uri);
}
private void requestIntent(Uri uri) {
Intent intent = new Intent(Intent.ACTION_VIEW);
FileNameMap mime = URLConnection.getFileNameMap();
String mimeType = mime.getContentTypeFor(uri.getPath());
intent.setDataAndType(uri, mimeType);
try {
mContext.startActivity(intent);
} catch (ActivityNotFoundException e) {
Toast.makeText(mContext, "No activity found to handle file",
Toast.LENGTH_LONG).show();
}
}
private void _download(ODataRow attachment) {
initNotificationManager(attachment.getString(KEY_FILE_NAME));
DownloadManager downloader = new DownloadManager(attachment,
notification_id++);
downloader.execute();
}
private class DownloadManager extends AsyncTask<Void, Void, Object> {
private int notification_id = -1;
private int server_id = -1;
private ODataRow attachment = null;
private Uri uri = null;
public DownloadManager(ODataRow row, int id) {
notification_id = id;
attachment = row;
server_id = row.getInt("id");
mNotificationBuilder.setProgress(0, 0, true);
mNotification = mNotificationBuilder.build();
mNotificationManager.notify(notification_id, mNotification);
}
@Override
protected Object doInBackground(Void... params) {
if (mApp.inNetwork()) {
String base64Data = mAttachment.getBase64Data(server_id, mApp);
if (!base64Data.equals("false")) {
String file = createFile(
attachment.getString(KEY_FILE_NAME),
Base64.decode(base64Data, 0),
attachment.getString(KEY_FILE_TYPE));
uri = Uri.fromFile(new File(file));
OValues values = new OValues();
values.put(KEY_FILE_URI, uri.toString());
mAttachment.update(values,
attachment.getInt(OColumn.ROW_ID));
return true;
}
}
return null;
}
@Override
protected void onPostExecute(Object result) {
super.onPostExecute(result);
if (result != null) {
mNotificationManager.cancel(notification_id);
if (mApp.inNetwork()) {
setSoundForNotification();
setVibrateForNotification();
setFileIntent(attachment, uri);
mNotification = mNotificationBuilder.build();
mNotificationManager.notify(notification_id, mNotification);
} else {
Toast.makeText(mContext, "No network !", Toast.LENGTH_LONG)
.show();
}
} else {
mNotificationManager.cancel(notification_id);
Toast.makeText(mContext, "Unable to download file !",
Toast.LENGTH_LONG).show();
}
}
}
private String createFile(String name, byte[] fileAsBytes, String file_type) {
InputStream is = new ByteArrayInputStream(fileAsBytes);
String filename = name.replaceAll("[-+^:=, ]", "_");
String file_path = getDirectoryPath(file_type) + "/" + filename;
try {
FileOutputStream fos = new FileOutputStream(file_path);
byte data[] = new byte[1024];
int count = 0;
while ((count = is.read(data)) != -1) {
fos.write(data, 0, count);
}
is.close();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
return file_path;
}
private String getDirectoryPath(String file_type) {
String path = getAppDirectoryPath();
if (file_type.contains("image")) {
path += "/Images";
} else if (file_type.contains("audio")) {
path += "/Audio";
} else {
path += "/Files";
}
File fileDir = new File(path);
if (!fileDir.isDirectory()) {
fileDir.mkdir();
}
return path;
}
private String getAppDirectoryPath() {
File externalStorage = Environment.getExternalStorageDirectory();
String basePath = externalStorage.getAbsolutePath() + "/Odoo";
File baseDir = new File(basePath);
if (!baseDir.isDirectory()) {
baseDir.mkdir();
}
return basePath;
}
private void initNotificationManager(String filename) {
mNotificationManager = (NotificationManager) mContext
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationBuilder = new NotificationCompat.Builder(mContext);
mNotificationBuilder.setContentTitle("Downloading " + filename);
mNotificationBuilder.setContentText("Download in progress");
mNotificationBuilder.setSmallIcon(R.drawable.ic_odoo_o);
mNotificationBuilder.setAutoCancel(true);
mNotificationBuilder.setOngoing(true);
}
private void setSoundForNotification() {
mNotificationBuilder.setVibrate(new long[] { 1000, 1000, 1000, 1000,
1000 });
}
private void setVibrateForNotification() {
Uri uri = RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
mNotificationBuilder.setSound(uri);
}
private void setFileIntent(ODataRow attachment, Uri uri) {
Log.v(TAG, "setFileIntent()");
String filename = attachment.getString(KEY_FILE_NAME);
Intent intent = new Intent(Intent.ACTION_VIEW);
FileNameMap mime = URLConnection.getFileNameMap();
String mimeType = mime.getContentTypeFor(uri.getPath());
intent.setDataAndType(uri, mimeType);
mNotificationResultIntent = PendingIntent.getActivity(mContext, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
mNotificationBuilder.addAction(R.drawable.ic_odoo_o, filename,
mNotificationResultIntent);
if (attachment.getString(KEY_FILE_TYPE).contains("image")) {
Bitmap bitmap = Base64Helper.getBitmapImage(
mContext,
Base64Helper.fileUriToBase64(uri,
mContext.getContentResolver()));
mNotificationBuilder
.setStyle(new NotificationCompat.BigPictureStyle()
.bigPicture(bitmap));
}
mNotificationBuilder.setOngoing(false);
mNotificationBuilder.setAutoCancel(true);
mNotificationBuilder.setContentTitle(filename);
mNotificationBuilder.setContentText("Download Complete");
mNotificationBuilder.setProgress(0, 0, false);
mNotificationBuilder.setContentIntent(mNotificationResultIntent);
mNotificationBuilder.setContentTitle("File downloaded");
mNotificationBuilder.setContentText("Download complete");
}
private void noFileFound() {
Toast.makeText(mContext, "Unable to find attachment !",
Toast.LENGTH_LONG).show();
}
private boolean fileExists(Uri uri) {
return new File(uri.getPath()).exists();
}
@SuppressLint("NewApi")
private String getKitKatDocPath(Uri uri) {
String wholeID = DocumentsContract.getDocumentId(uri);
String id = wholeID.split(":")[1];
String[] column = { MediaStore.Images.Media.DATA };
String sel = MediaStore.Images.Media._ID + "=?";
Cursor cursor = mContext.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel,
new String[] { id }, null);
String filePath = null;
int columnIndex = cursor.getColumnIndex(column[0]);
if (cursor.moveToFirst()) {
filePath = cursor.getString(columnIndex);
}
cursor.close();
return filePath;
}
private boolean isKitKat() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
}
@SuppressLint("InlinedApi")
public void newAttachment(Types type) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_GET_CONTENT);
switch (type) {
case IMAGE_OR_CAPTURE_IMAGE:
createDialog(type);
break;
case IMAGE:
if (Build.VERSION.SDK_INT < 19) {
intent = new Intent();
intent.setAction(Intent.ACTION_GET_CONTENT);
} else {
intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
}
intent.setType("image/*");
requestIntent(intent, REQUEST_IMAGE);
break;
case CAPTURE_IMAGE:
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "Odoo Mobile Attachment");
values.put(MediaStore.Images.Media.DESCRIPTION,
"Captured from Odoo Mobile App");
newImageUri = mContext.getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, newImageUri);
requestIntent(intent, REQUEST_CAMERA);
break;
case AUDIO:
intent.setType("audio/*");
requestIntent(intent, REQUEST_AUDIO);
break;
case FILE:
intent.setType("application/file");
requestIntent(intent, REQUEST_FILE);
break;
default:
break;
}
}
private void createDialog(Types type) {
mDialogType = type;
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
switch (type) {
case IMAGE_OR_CAPTURE_IMAGE:
builder.setTitle("Image");
mOptions = new String[] { "Select Image", "Capture Image" };
break;
default:
break;
}
builder.setSingleChoiceItems(mOptions, -1, this);
builder.create().show();
}
private void requestIntent(Intent intent, int requestCode) {
try {
((Activity) mContext).startActivityForResult(intent, requestCode);
} catch (ActivityNotFoundException e) {
Toast.makeText(mContext, "No Activity Found to handle request",
Toast.LENGTH_SHORT).show();
}
}
public OValues handleResult(int requestCode, Intent data) {
OValues attachment = new OValues();
switch (requestCode) {
case REQUEST_AUDIO:
case REQUEST_FILE:
case REQUEST_IMAGE:
attachment = getURIDetails(data.getData());
break;
case REQUEST_CAMERA:
attachment = getURIDetails(newImageUri);
break;
case SINGLE_ATTACHMENT_STREAM:
Uri uri = data.getParcelableExtra(Intent.EXTRA_STREAM);
attachment = getURIDetails(uri);
break;
default:
return null;
}
return attachment;
}
public OValues getURIDetails(Uri uri) {
OValues values = new OValues();
ContentResolver mCR = mContext.getContentResolver();
if (uri.getScheme().equals("content")) {
Cursor cr = mCR.query(uri, null, null, null, null);
int nameIndex = cr.getColumnIndex(OpenableColumns.DISPLAY_NAME);
int fileSize = cr.getColumnIndex(OpenableColumns.SIZE);
if (cr.moveToFirst()) {
values.put("name", cr.getString(nameIndex));
values.put("datas_fname", values.get("name"));
values.put("file_size", Long.toString(cr.getLong(fileSize)));
}
}
if (uri.getScheme().equals("file")) {
File file = new File(uri.toString());
values.put("name", file.getName());
values.put("datas_fname", values.get("name"));
values.put("file_size", Long.toString(file.length()));
}
values.put("file_uri", uri.toString());
values.put("scheme", uri.getScheme());
MimeTypeMap mime = MimeTypeMap.getSingleton();
String type = mime.getMimeTypeFromExtension(mime
.getExtensionFromMimeType(mCR.getType(uri)));
values.put("file_type", (type == null) ? uri.getScheme() : type);
values.put("type", type);
if (mAttachment.getColumn("write_date") != null)
values.put("write_date", ODate.getUTCDate(ODate.DEFAULT_FORMAT));
return values;
}
public int pushToServer(ODataRow row) {
int attachment_id = 0;
try {
IrAttachment attachment = new IrAttachment(mContext);
String base64 = Base64Helper.fileUriToBase64(
Uri.parse(row.getString("file_uri")),
mContext.getContentResolver());
row.put(KEY_DB_DATAS, base64);
row.put(KEY_TYPE, "binary");
attachment_id = attachment.getSyncHelper().create(attachment, row);
} catch (Exception e) {
e.printStackTrace();
}
return attachment_id;
}
@Override
public void onClick(DialogInterface dialog, int which) {
switch (mDialogType) {
case IMAGE_OR_CAPTURE_IMAGE:
newAttachment((which == 0) ? Types.IMAGE : Types.CAPTURE_IMAGE);
break;
default:
}
dialog.cancel();
}
public List<OValues> handleIntentRequest(Intent intent) {
List<OValues> attachments = new ArrayList<OValues>();
String action = intent.getAction();
// Handling single attachment request
if (Intent.ACTION_SEND.equals(action)) {
attachments.add(handleResult(SINGLE_ATTACHMENT_STREAM, intent));
}
// Handling multiple attachments request
if (Intent.ACTION_SEND_MULTIPLE.equals(action)) {
for (Parcelable attach : intent
.getParcelableArrayListExtra(Intent.EXTRA_STREAM)) {
Uri uri = (Uri) attach;
attachments.add(getURIDetails(uri));
}
}
return attachments;
}
}