package com.codefixia.selectlibrary; /** * SelectFile * Android library which provides Dialogs for selectInput(), selectFolder() and selectOutput() methods. * https://github.com/pif/android-select-file/tree/dlg * * Copyright (C) 2013 Ostap Andrusiv http://andrusiv.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA * * @author Ostap Andrusiv http://andrusiv.com * @modified 02/20/2013 * @version 0.0.1 (1) */ //package selectsrc.files; import java.io.File; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import processing.core.PApplet; import android.app.Dialog; import android.app.ProgressDialog; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.graphics.Color; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.os.IBinder; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ImageButton; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import com.codefixia.drumcloud.DrumCloud; import com.codefixia.drumcloud.R; import com.codefixia.googledrive.DownloadFile; import com.codefixia.googledrive.GoogleDriveService; import com.codefixia.googledrive.GoogleDriveService.MyLocalBinder; /** * Dialog, which provides * <ul> * <li>select file,</li> * <li>select folder,</li> * <li>save file</li> * functionality. * <br> * <br> * Usage: * {@see FileLibrary} * * @author ostap.andrusiv * */ public class SelectDialog extends Dialog { private static final String CURRENT_PATH = "currentPath"; private static boolean downloadPreview = false; public static final String EX_PATH = "extraPath"; public static final String EX_STYLE = "selectStyle"; public static final String EX_PATH_RESULT = "pathResult"; public static final String EX_CALLBACK = "selectCallback"; public static final String EX_TITLE = "selectTitle"; public static final String EX_FILTER_EXTENSION = "filterExtension"; public ProgressDialog mProgressDialog; private String currentPath = ""; private ArrayAdapter<FileItem> simpleAdapter = null; private SelectMode selectMode = null; private final Intent intent; private PApplet parent; private ListView listView = null; private String filterExtension = null; private FileItem lastSelectedFileItem=null; public static boolean localMode=false; public static boolean showMainOptions=true; private String currentFolderId=GoogleDriveService.googleDriveMainFolderId; //private String parentFolderId=GoogleDriveActivity.googleDriveMainFolderId; private String callbackMethod=null; GoogleDriveService driveService; boolean isBound = false; private ServiceConnection myConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { MyLocalBinder binder = (MyLocalBinder) service; driveService = binder.getService(); isBound = true; } public void onServiceDisconnected(ComponentName arg0) { isBound = false; } }; public SelectDialog(PApplet context, Intent intent) { super(context); this.parent = context; this.intent = intent; callbackMethod = intent.getStringExtra(SelectDialog.EX_CALLBACK); Intent i=new Intent(getContext(),GoogleDriveService.class); this.getContext().bindService(i, myConnection, Context.BIND_AUTO_CREATE); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(SelectConstants.generateMainActivityViews(getContext())); SelectDialog.showMainOptions=true; GoogleDriveService.delegate=this; listView = (ListView) findViewById(android.R.id.list); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View v, int position, long id) { onListItemClick((ListView) parent, v, position, id); } }); filterExtension=getIntent().getStringExtra(EX_FILTER_EXTENSION); //System.err.println("FILTER:"+filterExtension); setTitle(getIntent().getStringExtra(EX_TITLE)); currentPath = getIntent().getStringExtra(EX_PATH); if (currentPath == null) { currentPath = Environment.getExternalStorageDirectory().getAbsolutePath(); } if (savedInstanceState != null) { String savedPath = savedInstanceState.getString(CURRENT_PATH); if (savedPath != null) { currentPath = savedPath; } } selectMode = SelectMode.createSelectMode(getIntent().getIntExtra(EX_STYLE, SelectMode.SELECT_FILE), this); selectMode.updateUI(); simpleAdapter = new ArrayAdapter<FileItem>(getContext(), R.layout.file_list_item, android.R.id.text1) { @Override public View getView(int position, View convertView, ViewGroup parent) { View view = super.getView(position, convertView, parent); FileItem fItem = this.getItem(position); //view.setLayoutParams(new LayoutParams(android.widget.AbsListView.LayoutParams.FILL_PARENT, android.widget.AbsListView.LayoutParams.WRAP_CONTENT)); TextView tv1 = (TextView) view.findViewById(android.R.id.text1); if(fItem.getName().endsWith("json")){ tv1.setText(fItem.getName().replace(".json", " PACK")); view.setBackgroundColor(SelectConstants.COLOR_FILE_PACK); } else view.setBackgroundColor(fItem.getType().getColor()); tv1.setTextColor(Color.WHITE); tv1.setTextSize(15); tv1.setShadowLayer((float) 0.01, 1, 1,Color.BLACK); TextView tv2 = (TextView) view.findViewById(android.R.id.text2); tv2.setTextColor(Color.WHITE); tv2.setTextSize(10); tv2.setShadowLayer((float) 0.01, 1, 1,Color.BLACK); ImageButton play = (ImageButton) view.findViewById(R.id.imageButton1); play.setVisibility(View.VISIBLE); if(fItem.getName().equalsIgnoreCase("Up..")){ //play.setVisibility(View.GONE); play.setEnabled(false); play.setImageResource(R.drawable.ic_menu_back); if(fItem.isOnline) tv2.setText("Press to go back"); else tv2.setText("Press to go back to\n"+fItem.getFullPath()); }else if(fItem.getType()==FileType.Folder){ //play.setVisibility(View.GONE); play.setEnabled(false); play.setImageResource(R.drawable.ic_menu_archive); if(fItem.isOnline) tv2.setText(fItem.getFormattedCreationDate()+"\n"+fItem.getFormattedLastViewDate()); else tv2.setText("Path:\n"+fItem.getFullPath()); }else if(fItem.getType()==FileType.File){ tv2.setText(fItem.getFormattedLastModifiedDate()+"\n"+fItem.getFormattedSize()); //play.setText(R.string.play); play.setTag(fItem); if(fItem.getName().endsWith("json")){ play.setEnabled(false); play.setImageResource(R.drawable.ic_menu_moreoverflow); } else{ play.setEnabled(true); play.setImageResource(android.R.drawable.ic_media_play); } play.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final FileItem fItem=(FileItem) v.getTag(); Log.i("PREVIEW","File:"+fItem.getFile().getName()+" name:"+fItem.getName()); if(!fItem.isOnline){ if(fItem.getFile().exists()){ if(fItem.getName().endsWith("wav")){ MediaPlayer mp = MediaPlayer.create(getContext(), Uri.fromFile(fItem.getFile())); if(mp!=null) mp.start(); }else{ selectCallback(fItem.getFile(), "playSoundFile",DrumCloud.X); } }else{ Log.i("FILE ERROR","Unable to locate file:"+fItem.getFile().getAbsolutePath()); } }else{ downloadPreview=true; lastSelectedFileItem=fItem; GoogleDriveService.downloadFile(fItem.downloadUrl); } } }); } return view; } }; File f = new File(currentPath); updateCurrentList(f); setListAdapter(simpleAdapter); } private void setListAdapter(ArrayAdapter<FileItem> simpleAdapter) { listView.setAdapter(simpleAdapter); } void getMainOptions() { simpleAdapter.clear(); File local = new File(currentPath); FileItem localFiles=new FileItem("Local Files", FileType.Folder, local); simpleAdapter.add(localFiles); File drive = new File("https://drive.google.com/"); FileItem driveFiles=new FileItem("Google Drive", FileType.Folder, drive); simpleAdapter.add(driveFiles); simpleAdapter.notifyDataSetChanged(); } void updateCurrentList(File f) { if(showMainOptions){ getMainOptions(); } else{ if(localMode){ getLocalFolderList(f); } else{ requestDriveFolderList(currentFolderId,f.getName()); } } } void getLocalFolderList(File f){ List<FileItem> newData = getData(f); currentPath = f.getAbsolutePath(); simpleAdapter.clear(); for (FileItem item : newData) { simpleAdapter.add(item); } simpleAdapter.notifyDataSetChanged(); } void requestDriveFolderList(String folderId,String folderName) { mProgressDialog = new ProgressDialog(DrumCloud.X); mProgressDialog.setMessage("Loading Drive folder: "+(folderName==null?"MAIN":folderName)); mProgressDialog.setIndeterminate(true); mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); mProgressDialog.show(); Intent i=new Intent(getContext(),GoogleDriveService.class); i.putExtra("operation", "filesInFolder"); i.putExtra("folderId", folderId); getContext().startService(i); } public void callbackDriveFolderList(List<FileItem> newData) { simpleAdapter.clear(); Log.d("CALLBACK","Gathered "+newData.size()+" files"); sortFileItems(newData); if(currentFolderId!=null && !currentFolderId.equalsIgnoreCase(GoogleDriveService.googleDriveMainFolderId)){ FileItem upFileItem=new FileItem(SelectConstants.fs_up_item, FileType.Up, lastSelectedFileItem.getFile()); upFileItem.fileId=lastSelectedFileItem.parentFolderId; simpleAdapter.add(upFileItem); } for (FileItem item : newData) { simpleAdapter.add(item); } simpleAdapter.notifyDataSetChanged(); selectMode.updateUI(); mProgressDialog.hide(); if(!this.isShowing()){ this.show(); } } /** * 1. directories first * 2. dirs/files are sorted ignoring case */ private static final Comparator<File> sorter = new Comparator<File>() { @Override public int compare(File lhs, File rhs) { // file or folder int lhsType = lhs.isDirectory() ? 0 : 1; int rhsType = rhs.isDirectory() ? 0 : 1; if (lhsType != rhsType) { return lhsType - rhsType; } return lhs.getName().compareToIgnoreCase(rhs.getName()); } }; private static final Comparator<FileItem> sorter2 = new Comparator<FileItem>() { @Override public int compare(FileItem lhs, FileItem rhs) { // file or folder int lhsType = lhs.getType()==FileType.Folder ? 0 : 1; int rhsType = rhs.getType()==FileType.Folder ? 0 : 1; if (lhsType != rhsType) { return lhsType - rhsType; } return lhs.getName().compareToIgnoreCase(rhs.getName()); } }; private void sortData(File[] files) { Arrays.sort(files, sorter); } private void sortFileItems(List<FileItem> newData) { Collections.sort(newData, sorter2); } private List<FileItem> getData(File folder) { if (!folder.isDirectory()) { return Collections.emptyList(); } // selectMode specifies file-filtering rules File[] listFiles = folder.listFiles(selectMode); sortData(listFiles); List<FileItem> result = new ArrayList<FileItem>(); // add "Up one level" item File parentFolder = folder.getParentFile(); if (parentFolder != null) { result.add(new FileItem(SelectConstants.fs_up_item, FileType.Up, parentFolder)); } for (int i = 0; i < listFiles.length; i++) { File f = listFiles[i]; FileItem item = new FileItem( f.getName(), f.isDirectory() ? FileType.Folder : FileType.File, f); item.isOnline=false; if(!f.isDirectory()){ if(item.getFile().exists()){ item.size=item.getFile().length(); item.modifiedDate=item.getFile().lastModified(); } if(filterExtension!=null){ String[] extensions=filterExtension.split(";"); for(int i1=0;i1<extensions.length;i1++){ if(f.getName().toLowerCase().endsWith(extensions[i1].toLowerCase())){ result.add(item); } } }else{ result.add(item); } } else result.add(item); } return result; } protected void onListItemClick(ListView l, View v, int position, long id) { FileItem item = simpleAdapter.getItem(position); lastSelectedFileItem=item; selectMode.onItemClicked(item.getFile()); } /** * TODO: Probably, should be moved inside the {@link SelectLibrary#selectImpl(String, String, File, int)} method. * @param file */ protected void onFileSelected(File file, Intent intent) { Log.d("onFileSelected","Path:"+file.getAbsolutePath()+" b:"+file.getAbsolutePath().startsWith("https://drive.google.com")); if(localMode){ if (file != null) { //String callbackMethod = intent.getStringExtra(SelectDialog.EX_CALLBACK); selectCallback(file, callbackMethod, parent); if(!file.getAbsolutePath().endsWith("json")){ Intent i=new Intent(getContext(),GoogleDriveService.class); i.putExtra("filePath", file.getAbsolutePath()); i.putExtra("operation", "uploadFile"); getContext().startService(i); } } }else{ if (file != null) { DrumCloud.X.toggleAudio(); // instantiate it within the onCreate method mProgressDialog = new ProgressDialog(DrumCloud.X); mProgressDialog.setMessage("Downloading: "+lastSelectedFileItem.getName()); mProgressDialog.setIndeterminate(false); mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); if(lastSelectedFileItem.getType()==FileType.File){ if(!lastSelectedFileItem.getName().endsWith("json")){ mProgressDialog.setMax(1); }else{ mProgressDialog.setMax(16); } GoogleDriveService.downloadFile(lastSelectedFileItem.downloadUrl); } else { currentFolderId=lastSelectedFileItem.fileId; requestDriveFolderList(currentFolderId,lastSelectedFileItem.getName()); } //InputStream is=GoogleDriveActivity.downloadFile(file); /*if(is!=null){ }*/ } } } public void preDownloadCallback(InputStream is){ DownloadFile downloadFile = new DownloadFile(); downloadFile.input=is; downloadFile.delegate=this; downloadFile.filename=lastSelectedFileItem.getName(); downloadFile.execute(lastSelectedFileItem.downloadUrl); } public void postDownloadCallback(String outputFilePath){ Log.i("LOADING LOCAL FILE",outputFilePath); File output=new File(outputFilePath); if(downloadPreview){ downloadPreview=false; if(output.getName().endsWith("wav")){ MediaPlayer mp = MediaPlayer.create(getContext(), Uri.fromFile(output)); if(mp!=null) mp.start(); }else{ selectCallback(output, "playSoundFile", parent); } }else{ if(output.exists()){ if(!output.getName().endsWith("json")){ selectCallback(output, callbackMethod, parent); Toast.makeText(DrumCloud.X, "Sound downloaded: " + output.getName(), Toast.LENGTH_SHORT).show(); }else{ selectCallback(output, callbackMethod, parent); Toast.makeText(DrumCloud.X, "Downloading SoundPack: " + output.getName(), Toast.LENGTH_SHORT).show(); } }else{ Toast.makeText(DrumCloud.X, "Error downlading file:"+outputFilePath, Toast.LENGTH_SHORT).show(); } } } static private void selectCallback(File selectedFile, String callbackMethod, Object callbackObject) { try { Class<?> callbackClass = callbackObject.getClass(); // System.err.println(callbackClass + " clazz"); Method selectMethod = callbackClass.getMethod(callbackMethod, new Class[] { File.class }); // System.err.println(selectMethod + " method"); selectMethod.invoke(callbackObject, new Object[] { selectedFile }); } catch (IllegalAccessException iae) { System.err.println(callbackMethod + "() must be public"); } catch (InvocationTargetException ite) { ite.printStackTrace(); } catch (NoSuchMethodException nsme) { System.err.println(callbackMethod + "() could not be found"); } } // @Override // public boolean onKeyDown(int keyCode, KeyEvent event) { // if ((keyCode == KeyEvent.KEYCODE_BACK)) { // File parentFile = new File(currentPath).getParentFile(); // if (parentFile == null) { // // finita la comedia: returning to the calling activity // return super.onKeyDown(keyCode, event); // } else { // updateCurrentList(parentFile); // } // return true; // // } else { // return super.onKeyDown(keyCode, event); // } // } public String getCurrentPath() { return currentPath; } @Override public Bundle onSaveInstanceState() { Bundle outState = super.onSaveInstanceState(); outState.putString(CURRENT_PATH, currentPath); return outState; } public Intent getIntent() { return intent; } @Override public void onAttachedToWindow() { Log.d("ONATTACHED","onAttachedToWindow SelectDialog"); super.onAttachedToWindow(); } @Override public void onDetachedFromWindow() { Log.d("ONDETACHED","onDetachedFromWindow SelectDialog"); super.onDetachedFromWindow(); } }