package com.codefixia.googledrive;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import android.R;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.IntentService;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.net.Uri;
import android.os.Binder;
import android.os.Environment;
import android.os.IBinder;
import android.provider.MediaStore;
import android.util.Log;
import android.widget.Toast;
import com.codefixia.drumcloud.DrumCloud;
import com.codefixia.selectlibrary.FileItem;
import com.codefixia.selectlibrary.FileType;
import com.codefixia.selectlibrary.SelectDialog;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
import com.google.api.client.http.FileContent;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.Drive.Files;
import com.google.api.services.drive.model.ChildReference;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList;
public class GoogleDriveService extends IntentService {
static final int REQUEST_AUTHORIZATION = 2;
static final int CAPTURE_IMAGE = 3;
static final int REQUEST_FOLDER_FILES = 4;
private static Uri fileUri;
private static Drive service=null;
private java.io.File selectedFile=null;
private String filePath;
private String folderId;
private String operation;
private static Boolean uploadMode=false;
private String fileId;
final static public String googleDriveMainFolderId="0B7AaL1Q9Q5fTZGY2eG12WDc5aFU";
final static public String[] folderIds={"0B7AaL1Q9Q5fTb2RScXBFMGljTm8","0B7AaL1Q9Q5fTZGY2eG12WDc5aFU","0B7AaL1Q9Q5fTLWU1b1VkRXdvV00"};
final static public String[] folderNames={"/DrumCloud","/DrumCloud/Samples","/DrumCloud/Samples/DrumSets"};
final static public String[] folderCategoryIds={"0B7AaL1Q9Q5fTX1pjNnViTFMzVG8","0B7AaL1Q9Q5fTRHZHbldlbWFjREk","0B7AaL1Q9Q5fTMTZGaFFKM1JuVWc","0B7AaL1Q9Q5fTdVU1MTNuNkFJZHM","0B7AaL1Q9Q5fTYmJYUmR6MElvUDQ","0B7AaL1Q9Q5fTdVVOWEdQdFNNSEU","0B7AaL1Q9Q5fTbXBzZHIyaENQOFE","0B7AaL1Q9Q5fTYjlzeEg0LUJvMUE"};
final static public String[] folderCategoryNames={"Others","Kick","Bass","Snare","Hats","Percurssion","Synth","FX"};
private int categorySelected=-1;
private final IBinder myBinder = new MyLocalBinder();
public static SelectDialog delegate;
//private Activity mainActivity=DrumCloud.activity;
public GoogleDriveService() {
super("GoogleDriveService");
}
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
public class MyLocalBinder extends Binder {
public GoogleDriveService getService() {
return GoogleDriveService.this;
}
}
@Override
protected void onHandleIntent(Intent intent) {
String newOperation=intent.getStringExtra("operation");
Log.d("DRIVESERVICE","Last operation:\""+operation+"\" new:"+newOperation);
if(newOperation!=null && newOperation.length()>0){
operation=newOperation;
folderId=intent.getStringExtra("folderId");
filePath=intent.getStringExtra("filePath");
Log.d("DRIVESERVICE","Received operation:\""+operation+"\" folderId:"+folderId+" filePath:"+filePath);
if(service!=null){
processOperation(operation);
}else{
Intent i=new Intent(this,DummyActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//i.putExtra("operation", operation);
startActivity(i);
}
}else{//response from DummyActivity
int resultCode=intent.getIntExtra("resultCode",0);
int requestCode=intent.getIntExtra("requestCode",0);
if (resultCode == Activity.RESULT_OK && intent != null && intent.getExtras() != null) {
String accountName = intent.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
if (accountName != null) {
DummyActivity.getCredential().setSelectedAccountName(accountName);
service = getDriveService(DummyActivity.getCredential());
Log.d("DRIVESERVICE","Account name:"+accountName+" recovering operation:"+operation);
if(service!=null)
processOperation(operation);
}else{
returnCanceledLogin();
}
}else{
returnCanceledLogin();
}
}
}
public void processOperation(final String operation){
if(operation==null){
showToast("Undefined operation");
}else if(operation.equalsIgnoreCase("filesInFolder")){
filesInFolder(folderId);
}else if(operation.equalsIgnoreCase("startCameraIntent")){
startCameraIntent();
}else if(operation.equalsIgnoreCase("downloadFile")){
downloadFile(filePath);
}else if(operation.equalsIgnoreCase("uploadFile")){
uploadFile(filePath);
}else{
showToast("Unimplemented operation:"+operation);
}
}
private Drive getDriveService(GoogleAccountCredential credential) {
return new Drive.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), credential)
.build();
}
private void startCameraIntent() {
String mediaStorageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES).getPath();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date());
fileUri = Uri.fromFile(new java.io.File(mediaStorageDir + java.io.File.separator + "IMG_"
+ timeStamp + ".jpg"));
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
//startActivityForResult(cameraIntent, CAPTURE_IMAGE);
}
public String getFolderById(String fileId){
for(int i=0;i<folderIds.length;i++){
if(folderIds[i].equalsIgnoreCase(fileId))
return folderNames[i];
}
return "/UnknowFolder";
}
public void filesInFolder(final String folderId){
final GoogleDriveService GDS=this;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
List<FileItem> fileItemList=new ArrayList<FileItem>();
if(service==null){
Log.e("DRIVE SERVICE","ERROR NOT INITIALIZED");
returnFiles(fileItemList);
return;
}
Files.List request;
try {
request = service.files().list().setQ("'"+((folderId==null)?googleDriveMainFolderId:folderId)+"' in parents");
do {
//try {
FileList oneFile = request.execute();
for (File child : oneFile.getItems()) {
FileItem fileItem=getFileItem(child);
if(fileItem!=null)
fileItemList.add(fileItem);
System.out.println("File Id: " + child.toString());
}
request.setPageToken(oneFile.getNextPageToken());
//} catch (IOException e) {
// System.out.println("An error occurred: " + e);
// request.setPageToken(null);
//}
} while (request.getPageToken() != null &&
request.getPageToken().length() > 0);
} catch (final UserRecoverableAuthIOException e) {
Log.e("NOT AUTHORIZED","NOT AUTHORIZED");
requestAuth(GDS,e);
}catch (IOException e1) {
e1.printStackTrace();
}
returnFiles(fileItemList);
}
});
t.start();
}
private static void requestAuth(final Context context,final UserRecoverableAuthIOException e){
DrumCloud.X.runOnUiThread(new Runnable() {
@Override
public void run() {
delegate.hide();
Intent i=new Intent(DrumCloud.X,DummyActivity.class);
i.setAction("REQUEST_AUTHORIZATION");
//i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("operation", "REQUEST_AUTHORIZATION");
i.putExtra("intent", e.getIntent());
DrumCloud.X.startActivity(i);
DrumCloud.X.overridePendingTransition (R.anim.fade_in,R.anim.fade_out);
}
});
}
private void returnFiles(final List<FileItem> childs) {
DrumCloud.X.runOnUiThread(new Runnable() {
@Override
public void run() {
delegate.callbackDriveFolderList(childs);
}
});
//fa.finish();
}
private static void hideDialog() {
DrumCloud.X.runOnUiThread(new Runnable() {
@Override
public void run() {
delegate.hide();
}
});
}
private static FileItem getFileItem(String fileId) {
try {
Log.i("FILE INFO","File: " + fileId);
File file = service.files().get(fileId).execute();
FileItem item=new FileItem(file.getTitle(),(file.getFileSize()>0)?FileType.File:FileType.Folder,new java.io.File(file.getSelfLink()));
item.downloadUrl=file.getDownloadUrl();
item.fileId=fileId;
Log.i("FILE INFO","Download url: " + file.getDownloadUrl());
Log.i("FILE INFO","Title: " + file.getTitle());
Log.i("FILE INFO","MIME type: " + file.getMimeType());
return item;
}catch (UserRecoverableAuthIOException e) {
requestAuth(delegate.getContext(),e);
}catch (IOException e) {
Log.e("FILE INFO ERROR","An error occured: " + e);
}
return null;
}
private FileItem getFileItem(File file) {
FileType fileType=file.getMimeType().contains("folder")?FileType.Folder:FileType.File;
FileItem fileItem=new FileItem(file.getTitle(),fileType, new java.io.File(file.getSelfLink()) );
fileItem.downloadUrl=file.getDownloadUrl();
fileItem.parentFolderId=folderId;
fileItem.fileId=file.getId();
fileItem.extension=file.getFileExtension();
fileItem.size=file.getFileSize();
fileItem.isOnline=true;
if(file.getCreatedDate()!=null)
fileItem.creationDate=file.getCreatedDate().getValue();
if(file.getModifiedDate()!=null)
fileItem.modifiedDate=file.getModifiedDate().getValue();
if(file.getLastViewedByMeDate()!=null)
fileItem.lastView=file.getLastViewedByMeDate().getValue();
return fileItem;
}
/**
* Download a file's content.
*
* @param service Drive API service instance.
* @param file Drive File instance.
* @return InputStream containing the file's content if successful,
* {@code null} otherwise.
*/
public static void downloadFile(final String fileUrl) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
if (fileUrl != null && fileUrl.length() > 0) {
try {
HttpResponse resp =
service.getRequestFactory().buildGetRequest(new GenericUrl(fileUrl))
.execute();
returnInputStream(resp.getContent());
}catch (UserRecoverableAuthIOException e) {
requestAuth(delegate.getContext(),e);
}catch (IOException e) {
// An error occurred.
e.printStackTrace();
returnInputStream(null);
}
}else{
returnInputStream(null);
}
}
});
t.start();
}
public static void downloadFileByID(final String fileId,final String localPath) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
if (fileId != null && fileId.length() > 0) {
try {
FileItem fileItem=getFileItem(fileId);
String fileUrl=fileItem.downloadUrl;
if(fileUrl!=null && fileUrl.length()>0){
HttpResponse resp =
service.getRequestFactory().buildGetRequest(new GenericUrl(fileUrl))
.execute();
DownloadFile downloadFile = new DownloadFile();
downloadFile.input=resp.getContent();
downloadFile.filename=fileItem.getName();
downloadFile.localPath=localPath.replace(downloadFile.filename, "");
downloadFile.execute(fileUrl);
}else{
DownloadFile.incDownloaded();
Log.e("DRIVE","Error obtaining downloadUrl of:"+fileId);
}
}catch (UserRecoverableAuthIOException e) {
DownloadFile.incDownloaded();
requestAuth(delegate.getContext(),e);
}catch (IOException e) {
// An error occurred.
DownloadFile.incDownloaded();
e.printStackTrace();
}
}
}
});
t.start();
}
private static void returnInputStream(final InputStream is) {
DrumCloud.X.runOnUiThread(new Runnable() {
@Override
public void run() {
delegate.preDownloadCallback(is);
}
});
}
private static void returnCanceledLogin() {
DrumCloud.X.runOnUiThread(new Runnable() {
@Override
public void run() {
if(delegate!=null && delegate.mProgressDialog!=null){
delegate.mProgressDialog.dismiss();
}
Toast.makeText(DrumCloud.X, "Login on Google Drive canceled", Toast.LENGTH_SHORT).show();
delegate.dismiss();
}
});
}
private void uploadFile(final String localFilePath) {
final GoogleDriveService GDS=this;
AlertDialog.Builder d = new AlertDialog.Builder(DrumCloud.X).
//setMessage("Select the category of the sample.").
setTitle("Do you want to upload and share your sample on Google Drive?");
d.setSingleChoiceItems(folderCategoryNames, 0 , new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
String str = folderCategoryNames[which];
categorySelected=which;
Toast.makeText(DrumCloud.X,
"You have selected the \""+str+"\" sample category.",
Toast.LENGTH_LONG).show();
}
});
d.setNegativeButton("Cancel",new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
//fa.finish();
}
});
d.setPositiveButton("Save", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
final int selected=categorySelected;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
String selectedFolderID=folderCategoryIds[0];
if(selected>=0 && selected<folderCategoryIds.length){
selectedFolderID=folderCategoryIds[selected];
Log.d("CATEGORY",folderCategoryNames[selected]);
}
if(selectedFolderID==null)
selectedFolderID=googleDriveMainFolderId;
// File's binary content
if(localFilePath!=null){
Log.d("FILE TO UPLOAD", "PATH:"+localFilePath);
selectedFile=new java.io.File(localFilePath);
}else{
showToast("Error uploading sound");
return;
}
FileContent mediaContent = new FileContent("audio/wav", selectedFile);
Log.d("FILE TO UPLOAD", selectedFile.getAbsolutePath());
// File's metadata.
File body = new File();
body.setTitle(selectedFile.getName());
body.setMimeType("audio/wav");
File file = service.files().insert(body, mediaContent).execute();
if (file != null) {
showToast("Sound uploaded: " + file.getTitle());
ChildReference newChild = new ChildReference();
newChild.setId(file.getId());
try {
newChild=service.children().insert(selectedFolderID, newChild).execute();
Log.i("FILE INSERTED",newChild.getChildLink());
} catch (IOException e) {
Log.e("ERROR INSERTING IN FOLDER","An error occurred inserting file in main folder: " + e);
}
}else{
Log.e("UPLOAD ERROR", "Error while uploading:"+selectedFile.getName());
}
} catch (UserRecoverableAuthIOException e) {
requestAuth(delegate.getContext(),e);
} catch (IOException e) {
e.printStackTrace();
}
}
});
t.start();
}
});
d.show();
}
public void showToast(final String toast) {
DrumCloud.X.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(DrumCloud.X, toast, Toast.LENGTH_SHORT).show();
//fa.finish();
}
});
}
@Override
public void onDestroy()
{
Log.d("ONDESTROY","Detroying GoogleDriveService");
super.onDestroy();
}
}