package com.door43.translationstudio; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.support.v4.provider.DocumentFile; import android.view.Gravity; import android.view.View; import android.widget.AdapterView; import android.widget.Button; import android.widget.ImageButton; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import com.door43.translationstudio.core.Translator; import com.door43.translationstudio.dialogs.CustomAlertDialog; import com.door43.translationstudio.filebrowser.DocumentFileBrowserAdapter; import com.door43.translationstudio.filebrowser.DocumentFileItem; import com.door43.translationstudio.newui.BaseActivity; import com.door43.translationstudio.newui.home.ImportDialog; import com.door43.translationstudio.util.SdUtils; import java.io.File; import java.util.ArrayList; import java.util.List; /** * Created by blm on 12/31/15. */ public class ImportFileChooserActivity extends BaseActivity { public static final String EXTRAS_ACCEPTED_EXTENSIONS = "extras_accepted_file_extensions"; public static final String FOLDER_KEY = "folder"; public static final String FILE_PATH_KEY = "file_path"; public static final String SD_CARD_TYPE = "sd_card"; public static final String INTERNAL_TYPE = "internal"; private ImageButton mUpButton; private Button mInternalButton; private Button mSdCardButton; private Button mCancelButton; private Button mConfirmButton; private TextView mCurrentFolder; private ListView mFileList; private DocumentFileBrowserAdapter mAdapter; private DocumentFile mCurrentDir; private String mType; private String[] mAcceptedExtensions = { Translator.ARCHIVE_EXTENSION }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_choose_import_file); mUpButton = (ImageButton) findViewById(R.id.up_folder_button); mInternalButton = (Button) findViewById(R.id.internal_button); mSdCardButton = (Button) findViewById(R.id.sd_card_button); mCancelButton = (Button) findViewById(R.id.cancel_button); mConfirmButton = (Button) findViewById(R.id.confirm_button); mCurrentFolder = (TextView) findViewById(R.id.current_folder); mFileList = (ListView) findViewById(R.id.file_list); setTitle(R.string.title_activity_file_explorer); File sdCardFolder = SdUtils.getSdCardDirectory(); boolean haveSDCard = sdCardFolder != null; showSdCardOption(haveSDCard); mUpButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { DocumentFile parent = mCurrentDir.getParentFile(); loadDocFileList(parent); } }); mConfirmButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { boolean itemSelected = false; DocumentFileItem selectedItem = null; int position = mFileList.getCheckedItemPosition(); if (position >= 0) { selectedItem = mAdapter.getItem(position); if (isUsableFileName(selectedItem)) { itemSelected = true; } } if (itemSelected) { returnSelectedFile(selectedItem); } else { final CustomAlertDialog dialog = CustomAlertDialog.Create(ImportFileChooserActivity.this); dialog.setTitle(R.string.title_activity_file_explorer) .setMessageHtml(R.string.no_item_selected) .setPositiveButton(R.string.confirm, null) .show("no_selection"); } } }); mCancelButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { cancel(); } }); mInternalButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { showFileFolderFromInternalMemory(); } }); mSdCardButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (SdUtils.doWeNeedToRequestSdCardAccess()) { final CustomAlertDialog dialog = CustomAlertDialog.Create(ImportFileChooserActivity.this); dialog.setTitle(R.string.enable_sd_card_access_title) .setMessageHtml(R.string.enable_sd_card_access) .setPositiveButton(R.string.confirm, new View.OnClickListener() { @Override public void onClick(View v) { SdUtils.triggerStorageAccessFramework(ImportFileChooserActivity.this); } }) .setNegativeButton(R.string.label_skip, null) .show("approve-SD-access"); } else { showFolderFromSdCard(); } } }); mFileList.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { DocumentFileItem selectedItem = mAdapter.getItem(position); if (selectedItem.file.isDirectory()) { mAdapter.setSelectedPosition(-1); mFileList.clearChoices(); loadDocFileList(selectedItem.file); return; } else { // file item selected if (isUsableFileName(selectedItem)) { mAdapter.setSelectedPosition(position); mFileList.setItemChecked(position, true); return; } } //clear selections mAdapter.setSelectedPosition(-1); mFileList.clearChoices(); } }); Intent intent = getIntent(); mType = intent.getType(); Bundle args = intent.getExtras(); if(args != null) { String extenstions = args.getString(EXTRAS_ACCEPTED_EXTENSIONS, null); if (extenstions != null) { mAcceptedExtensions = extenstions.split(","); } } showFolderFromSdCard(); } /** * returns true if the filename extension for item matches list that we are accepting * @param item * @return */ private boolean isUsableFileName(DocumentFileItem item) { for (String acceptedExtension : mAcceptedExtensions) { if (item.isFileMatchesExtension(acceptedExtension)) { return true; } } return false; } /** * if sd card is available this will display buttons for "internal" and "sd card". * Otherwise neither will be displayed since we cannot switch. * @param haveSDCard */ private void showSdCardOption(boolean haveSDCard) { mSdCardButton.setVisibility( haveSDCard ? View.VISIBLE : View.GONE); mInternalButton.setVisibility( haveSDCard ? View.VISIBLE : View.GONE); } /** * will display file list for SD card folder if accessible. * Otherwise it will display file list from internal memory. */ private void showFolderFromSdCard() { DocumentFile path = null; boolean sdCardFound = false; boolean sdCardHaveAccess = false; boolean isSdCardPresentLollipop = SdUtils.isSdCardPresentLollipop(); if (isSdCardPresentLollipop) { sdCardFound = true; DocumentFile baseFolder = SdUtils.sdCardMkdirs(null); String subFolder = SdUtils.searchFolderAndParentsForDocFile(baseFolder, Translator.ARCHIVE_EXTENSION); if (null != subFolder) { path = SdUtils.documentFileMkdirs(baseFolder, subFolder); } else { path = SdUtils.documentFileMkdirs(baseFolder, SdUtils.DOWNLOAD_FOLDER); // use downloads folder, or make if not present. if (null == path) { path = baseFolder; // if folder creation fails, fall back to base folder } } if(null != path) { sdCardHaveAccess = true; loadDocFileList(path); } } else { // SD card not present or not lollipop File sdCardFolder = SdUtils.getSdCardDirectory(); if (sdCardFolder != null) { if (sdCardFolder.isDirectory() && sdCardFolder.exists() && sdCardFolder.canRead()) { File storagePath = Environment.getExternalStorageDirectory(); if(!sdCardFolder.equals(storagePath)) { // make sure it doesn't reflect back to internal memory sdCardFound = true; sdCardHaveAccess = true; showFileFolder(sdCardFolder); } } } } showSdCardOption(sdCardFound); if (!sdCardHaveAccess) { showFileFolderFromInternalMemory(); } } /** * will display file list for external storage directory */ private void showFileFolderFromInternalMemory() { File storagePath = Environment.getExternalStorageDirectory(); showFileFolder(storagePath); } /** * will display file list for specified Folder * @param storagePath */ private void showFileFolder(File storagePath) { DocumentFile path = null; DocumentFile baseFolder = DocumentFile.fromFile(storagePath); String subFolder = SdUtils.searchFolderAndParentsForDocFile(baseFolder, Translator.ARCHIVE_EXTENSION); if (null != subFolder) { path = SdUtils.documentFileMkdirs(baseFolder, subFolder); }else { path = SdUtils.documentFileMkdirs(baseFolder, SdUtils.DOWNLOAD_FOLDER); // use downloads folder, or make if not present. } if(null == path) { path = baseFolder; // if nothing is found, then default to base } loadDocFileList(path); } /** * returns the selected file to calling activity * @param selectedItem */ private void returnSelectedFile(DocumentFileItem selectedItem) { // return selected file Intent intent = getIntent(); intent.setData(selectedItem.file.getUri()); setResult(RESULT_OK, intent); finish(); } /** * notify calling activity that user has cancelled */ private void cancel() { Intent intent = getIntent(); intent.setData(null); setResult(RESULT_CANCELED, intent); finish(); } /** * Generates a list of files to display from a directory * @param dir * @return */ private void loadDocFileList(DocumentFile dir) { mAdapter = new DocumentFileBrowserAdapter(); mFileList.setAdapter(mAdapter); Context context = AppContext.context(); List<DocumentFileItem> fileList = new ArrayList<>(); mFileList.clearFocus(); mFileList.clearChoices(); mUpButton.setVisibility(View.GONE); if ((dir != null) && dir.exists() && dir.isDirectory()) { // remember directory mCurrentDir = dir; mCurrentFolder.setText(SdUtils.getPathString(dir)); // list files DocumentFile[] files = dir.listFiles(); if(files != null) { for (DocumentFile f : files) { if( !f.canRead() ) { continue; // skip if not readable } if (f.isDirectory()) { fileList.add(DocumentFileItem.getInstance(context, f)); } else { fileList.add(DocumentFileItem.getInstance(context, f)); } } // add up button if (dir.getParentFile() != null && dir.getParentFile().exists() && dir.getParentFile().canRead()) { mUpButton.setVisibility(View.VISIBLE); } } } mAdapter.loadFiles(this, fileList); if(fileList.size() <= 0) { Toast toast = Toast.makeText(this, R.string.empty_directory, Toast.LENGTH_SHORT); toast.setGravity(Gravity.TOP, 0, 0); toast.show(); } } @Override public void onResume() { super.onResume(); } public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == SdUtils.REQUEST_CODE_STORAGE_ACCESS) { Uri treeUri = null; String msg = ""; if (resultCode == Activity.RESULT_OK) { // Get Uri from Storage Access Framework. treeUri = data.getData(); final int takeFlags = data.getFlags(); boolean success = SdUtils.validateSdCardWriteAccess(treeUri, takeFlags); if (!success) { String template = getResources().getString(R.string.access_failed); msg = String.format(template, treeUri.toString()); } else { msg = getResources().getString(R.string.access_granted_import); showFolderFromSdCard(); } } else { msg = getResources().getString(R.string.access_skipped); } CustomAlertDialog.Create(this) .setTitle(R.string.access_title) .setMessage(msg) .setPositiveButton(R.string.label_ok, null) .show("AccessResults"); } } }