diff --git a/.travis.yml b/.travis.yml
index 1fe5dcb..b3ece8d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,10 +7,10 @@ android:
# - tools
# The BuildTools version used by your project
- - build-tools-19.1.0
+ - build-tools-22.0.1
# The SDK version used to compile your project
- - android-19
+ - android-22
# Additional components
- extra-google-m2repository
diff --git a/android_commons.gradle b/android_commons.gradle
index bab67bd..bb3c81f 100644
--- a/android_commons.gradle
+++ b/android_commons.gradle
@@ -5,12 +5,12 @@ repositories {
android {
- compileSdkVersion 21
- buildToolsVersion '21.1.2'
+ compileSdkVersion 22
+ buildToolsVersion '22.0.1'
defaultConfig {
minSdkVersion 14
- targetSdkVersion 21
+ targetSdkVersion 22
}
lintOptions {
diff --git a/app/build.gradle b/app/build.gradle
index 3f7ce20..e9b166f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -15,9 +15,9 @@ dependencies {
compile 'commons-io:commons-io:2.4'
- compile 'com.android.support:appcompat-v7:21.0.3'
+ compile 'com.android.support:appcompat-v7:22.1.1'
compile 'com.android.support:recyclerview-v7:21.0.3'
- compile 'com.android.support:support-v4:21.0.3'
+ compile 'com.android.support:support-v4:22.1.1'
compile 'com.github.chrisbanes.photoview:library:1.2.3'
compile 'com.path:android-priority-jobqueue:1.1.2'
compile 'de.greenrobot:eventbus:2.2.0'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4ec482d..a685066 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -28,9 +28,9 @@
android:resource="@xml/file_path" />
-
+
-
diff --git a/app/src/main/java/com/doplgangr/secrecy/activities/ChooseFolder.java b/app/src/main/java/com/doplgangr/secrecy/activities/ChooseFolder.java
deleted file mode 100644
index b7af611..0000000
--- a/app/src/main/java/com/doplgangr/secrecy/activities/ChooseFolder.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.doplgangr.secrecy.activities;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
-import android.view.MenuItem;
-
-import com.doplgangr.secrecy.R;
-import com.ipaulpro.afilechooser.FileChooserActivity;
-
-import java.util.ArrayList;
-
-
-public class ChooseFolder extends ActionBarActivity {
- private static final int REQUEST_CODE = 6384; // onActivityResult request code
- private static final ArrayList INCLUDE_EXTENSIONS_LIST = new ArrayList();
-
- static {
- INCLUDE_EXTENSIONS_LIST.add(".");
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- Intent intent = new Intent(this, FileChooserActivity.class);
-
- intent.putStringArrayListExtra(
- FileChooserActivity.EXTRA_FILTER_INCLUDE_EXTENSIONS,
- INCLUDE_EXTENSIONS_LIST);
- intent.putExtra(FileChooserActivity.EXTRA_SELECT_FOLDER, true);
- startActivityForResult(intent, REQUEST_CODE);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- // Handle action bar item clicks here. The action bar will
- // automatically handle clicks on the Home/Up button, so long
- // as you specify a parent activity in AndroidManifest.xml.
- int id = item.getItemId();
- return id == R.id.action_settings || super.onOptionsItemSelected(item);
- }
-
-}
diff --git a/app/src/main/java/com/doplgangr/secrecy/activities/FileChooserActivity.java b/app/src/main/java/com/doplgangr/secrecy/activities/FileChooserActivity.java
new file mode 100644
index 0000000..1378b53
--- /dev/null
+++ b/app/src/main/java/com/doplgangr/secrecy/activities/FileChooserActivity.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.doplgangr.secrecy.activities;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v7.app.ActionBarActivity;
+import android.support.v7.widget.Toolbar;
+import android.util.Log;
+
+import com.doplgangr.secrecy.R;
+import com.doplgangr.secrecy.fragments.FileChooserFragment;
+
+import java.io.File;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+
+
+public class FileChooserActivity extends ActionBarActivity implements FileChooserFragment.OnFileChosen{
+ public static final String FOLDERS_ONLY = "FOLDERS_ONLY"; // folders only extra
+ public static final String FILE_SELECTED = "FILE_SELECTED"; // selected file extra
+ public static final String ROOT_FOLDER = "ROOT_FOLDER"; // root folder extra
+ public static final String FILE_EXTENSIONS = "FILE_EXTENSIONS"; // file extensions to show
+ private File root = null;
+ private Boolean foldersOnly = false;
+ private ArrayList fileExtensions = new ArrayList<>();
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_file_chooser);
+ Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
+ if (mToolbar!=null)
+ setSupportActionBar(mToolbar);
+ Intent intent = getIntent();
+ if (intent!=null) {
+ String root_folder = intent.getStringExtra(ROOT_FOLDER);
+ if (root_folder!=null)
+ root=new File(root_folder);
+ foldersOnly = intent.getBooleanExtra(FOLDERS_ONLY, false);
+ fileExtensions = intent.getStringArrayListExtra(FILE_EXTENSIONS);
+ }
+ FileChooserFragment fragment = FileChooserFragment.newInstance(root, foldersOnly, fileExtensions);
+ getFragmentManager().beginTransaction()
+ .replace(R.id.content_frame, fragment)
+ .setTransition(android.support.v4.app.FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
+ .commit();
+ }
+
+ @Override
+ public void onFileSelected(File path, Boolean confirmed) {
+ if (confirmed) {
+ Intent returnIntent = new Intent();
+ returnIntent.putExtra(FILE_SELECTED,path);
+ setResult(RESULT_OK, returnIntent);
+ finish();
+ }else {
+ FileChooserFragment fragment = FileChooserFragment.newInstance(path, foldersOnly, fileExtensions);
+ getFragmentManager().beginTransaction()
+ .replace(R.id.content_frame, fragment)
+ .setTransition(android.support.v4.app.FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
+ .addToBackStack(path.getAbsolutePath()).commit();
+ }
+ }
+}
diff --git a/app/src/main/java/com/doplgangr/secrecy/adapters/FileChooserAdapter.java b/app/src/main/java/com/doplgangr/secrecy/adapters/FileChooserAdapter.java
new file mode 100644
index 0000000..926cc8e
--- /dev/null
+++ b/app/src/main/java/com/doplgangr/secrecy/adapters/FileChooserAdapter.java
@@ -0,0 +1,130 @@
+package com.doplgangr.secrecy.adapters;
+
+import android.app.Activity;
+import android.content.Context;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.doplgangr.secrecy.R;
+import com.doplgangr.secrecy.filesystem.Storage;
+import com.doplgangr.secrecy.fragments.FileChooserFragment;
+import com.doplgangr.secrecy.utils.Util;
+
+import java.io.File;
+import java.util.List;
+
+public class FileChooserAdapter extends RecyclerView.Adapter {
+
+ private Context context;
+ /**
+ * Inflater of the context;
+ */
+ private LayoutInflater inflater;
+ /**
+ * File object of the directory to be displayed
+ */
+ private File rootFile;
+ /**
+ * File object of the children to the directory to be displayed
+ */
+ private List files;
+
+ private FileChooserFragment.OnFileChosen mListener;
+
+
+ public FileChooserAdapter(Activity context,
+ List files, File rootFile, FileChooserFragment.OnFileChosen mListener) {
+ this.context = context;
+ this.inflater = context.getLayoutInflater();
+ this.files = files;
+ this.rootFile = rootFile;
+ this.mListener = mListener;
+ }
+
+ @Override
+ public FileChooserViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ return new FileChooserViewHolder(inflater.inflate(R.layout.listitem_single_line_text, parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(FileChooserViewHolder holder, int position) {
+
+ final File item = files.get(position);
+ Boolean isParent = rootFile.getParentFile()!=null && rootFile.getParentFile().getAbsolutePath().equals(item.getAbsolutePath());
+ Boolean isFile = item.isFile();
+ Boolean isReadableDir = Util.canReadDir(item);
+
+ if (holder.textView!=null){
+ // TODO: create a more intuitive way to let user know this is "up"
+ // If the rootFile has a parent, display as "up"
+ if (isParent)
+ holder.textView.setText("..");
+ else {
+ holder.textView.setText(item.getName());
+ }
+ holder.textView.setEnabled(isFile || isReadableDir);
+ if (isSubDirectory(item, Storage.getRoot()) && !isParent)
+ holder.textView.setTextColor(context.getResources().getColor(R.color.accent));
+ else
+ holder.textView.setTextColor(context.getResources().getColor(R.color.text_primary));
+ }
+ if (holder.iconView!=null){
+ if (isFile)
+ holder.iconView.setImageResource(R.drawable.ic_file);
+ if (isReadableDir)
+ holder.iconView.setImageResource(R.drawable.ic_action_folder);
+ if (isSubDirectory(item, Storage.getRoot()) && !isParent)
+ holder.iconView.setColorFilter(context.getResources().getColor(R.color.accent));
+ else
+ holder.iconView.setColorFilter(context.getResources().getColor(R.color.button));
+ }
+ holder.itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (null != mListener) {
+ // Notify the active callbacks interface (the activity, if the
+ // fragment is attached to one) that an item has been selected.
+ if (Util.canReadDir(item))
+ mListener.onFileSelected(item, false);
+ else
+ mListener.onFileSelected(item, true);
+ }
+ }
+ });
+ }
+
+ @Override
+ public int getItemCount() {
+ if (files!=null)
+ return files.size();
+ return 0;
+ }
+
+ /**
+ * Checks whether a directory is a subdirectory under certain root directory
+ * @param directory root directory to be checked against
+ * @param file file suspected of being a subdirectory
+ * @return true if file is in directory, false if not.
+ */
+ public static boolean isSubDirectory(File directory, File file) {
+ if (file == null)
+ return false;
+ if (file.equals(directory))
+ return true;
+ return isSubDirectory(directory, file.getParentFile());
+ }
+
+ public class FileChooserViewHolder extends RecyclerView.ViewHolder{
+ TextView textView;
+ ImageView iconView;
+ public FileChooserViewHolder(View itemView) {
+ super(itemView);
+ textView =(TextView) itemView.findViewById(R.id.text1);
+ iconView =(ImageView) itemView.findViewById(R.id.icon1);
+ }
+ }
+}
diff --git a/app/src/main/java/com/doplgangr/secrecy/adapters/VaultsListFragment.java b/app/src/main/java/com/doplgangr/secrecy/adapters/VaultsListFragment.java
index 2bbf6d9..7292efd 100644
--- a/app/src/main/java/com/doplgangr/secrecy/adapters/VaultsListFragment.java
+++ b/app/src/main/java/com/doplgangr/secrecy/adapters/VaultsListFragment.java
@@ -50,6 +50,7 @@
import com.doplgangr.secrecy.CustomApp;
import com.doplgangr.secrecy.R;
+import com.doplgangr.secrecy.activities.FileChooserActivity;
import com.doplgangr.secrecy.utils.Util;
import com.doplgangr.secrecy.activities.FilesActivity;
import com.doplgangr.secrecy.events.RestoreDoneEvent;
@@ -59,12 +60,14 @@
import com.doplgangr.secrecy.filesystem.encryption.VaultHolder;
import com.doplgangr.secrecy.jobs.RestoreJob;
import com.doplgangr.secrecy.fragments.SettingsFragment;
-import com.ipaulpro.afilechooser.FileChooserActivity;
import com.ipaulpro.afilechooser.utils.FileUtils;
+import org.apache.commons.io.FilenameUtils;
+
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.zip.ZipFile;
import de.greenrobot.event.EventBus;
@@ -294,15 +297,12 @@ public void onClick(DialogInterface dialog, int whichButton) {
}
void restore() {
- ArrayList INCLUDE_EXTENSIONS_LIST = new ArrayList();
- INCLUDE_EXTENSIONS_LIST.add(".zip");
-
+ ArrayList fileExtensions = new ArrayList<>();
+ fileExtensions.add("zip");
Intent intent = new Intent(context, FileChooserActivity.class);
+ intent.putExtra(FileChooserActivity.ROOT_FOLDER, Storage.getRoot().getAbsolutePath());
+ intent.putExtra(FileChooserActivity.FILE_EXTENSIONS, fileExtensions);
- intent.putStringArrayListExtra(
- FileChooserActivity.EXTRA_FILTER_INCLUDE_EXTENSIONS,
- INCLUDE_EXTENSIONS_LIST);
- intent.putExtra(FileChooserActivity.PATH, Storage.getRoot().getAbsolutePath());
startActivityForResult(intent, REQUESTCODE);
}
@@ -382,8 +382,7 @@ public void run() {
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- final Uri uri = data.getData();
- final String path = FileUtils.getPath(context, uri);
+ final File file = (File) data.getSerializableExtra(FileChooserActivity.FILE_SELECTED);
mNotifyManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(context);
mBuilder.setContentTitle(CustomApp.context.getString(R.string.Restore__title))
@@ -392,7 +391,7 @@ public void onClick(DialogInterface dialog, int which) {
.setOngoing(true);
mBuilder.setProgress(0, 0, true);
mNotifyManager.notify(REQUESTCODE, mBuilder.build());
- CustomApp.jobManager.addJobInBackground(new RestoreJob(context, new File(path)));
+ CustomApp.jobManager.addJobInBackground(new RestoreJob(context, file));
}
},
diff --git a/app/src/main/java/com/doplgangr/secrecy/fragments/FileChooserFragment.java b/app/src/main/java/com/doplgangr/secrecy/fragments/FileChooserFragment.java
new file mode 100644
index 0000000..2b58cd0
--- /dev/null
+++ b/app/src/main/java/com/doplgangr/secrecy/fragments/FileChooserFragment.java
@@ -0,0 +1,248 @@
+package com.doplgangr.secrecy.fragments;
+
+import android.app.Activity;
+import android.support.v7.app.AlertDialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.app.Fragment;
+import android.os.Environment;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.EditText;
+
+import com.doplgangr.secrecy.R;
+import com.doplgangr.secrecy.activities.FileChooserActivity;
+import com.doplgangr.secrecy.adapters.FileChooserAdapter;
+
+import org.apache.commons.io.FilenameUtils;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * A fragment to display a file chooser interface
+ */
+public class FileChooserFragment extends Fragment {
+
+ /**
+ * Fragment parameter ROOT
+ * String, denotes absolute path of the file root to display
+ */
+ private static final String ROOT = "root";
+ /**
+ * Fragment parameter FOLDERS_ONLY
+ * Boolean, if only folders should be displayed on the interface
+ */
+ private static final String FOLDERS_ONLY = "folders_only";
+
+ private List ITEMS = new ArrayList<>();
+
+ private OnFileChosen mListener;
+
+ /**
+ * The fragment's ListView/GridView.
+ */
+ private RecyclerView mRecyclerView;
+
+ /**
+ * The Adapter which will be used to populate the ListView/GridView with
+ * Views.
+ */
+ private FileChooserAdapter mAdapter;
+
+ /**
+ * The location of directory where views are displaying.
+ */
+ private File rootFile;
+
+ /**
+ * If only folders should be displayed. Additional menu icon "OK"
+ * Will be displayed to allow confirming. Additional add folder icon
+ * will also be added.
+ */
+ private Boolean foldersOnly;
+
+
+ /**
+ * The extensions that will be displayed.
+ */
+ private ArrayList fileExtensions;
+
+ public static FileChooserFragment newInstance(File root, Boolean foldersOnly, ArrayList fileExtensions) {
+ FileChooserFragment fragment = new FileChooserFragment();
+ Bundle args = new Bundle();
+
+ // Default implementation: accessing the internal SDcard.
+ if (root!=null)
+ args.putString(ROOT, root.getAbsolutePath());
+ else
+ args.putString(ROOT, Environment.getExternalStorageDirectory().getAbsolutePath());
+
+ // Default implementation: displaying all files and directory
+ if (foldersOnly!=null)
+ args.putBoolean(FOLDERS_ONLY, foldersOnly);
+ else
+ args.putBoolean(FOLDERS_ONLY, false);
+
+ args.putStringArrayList(FileChooserActivity.FILE_EXTENSIONS, fileExtensions);
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ /**
+ * Mandatory empty constructor for the fragment manager to instantiate the
+ * fragment (e.g. upon screen orientation changes).
+ */
+ public FileChooserFragment() {
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (getArguments() != null) {
+ rootFile = new File(getArguments().getString(ROOT));
+ foldersOnly = getArguments().getBoolean(FOLDERS_ONLY, false);
+ fileExtensions = getArguments().getStringArrayList(FileChooserActivity.FILE_EXTENSIONS);
+ }else{
+ rootFile = Environment.getExternalStorageDirectory();
+ foldersOnly = false;
+ fileExtensions = null;
+ }
+
+ // If a parent exists, add the parent to the list of children so that users can traverse up.
+ if (!Environment.getRootDirectory().equals(rootFile.getAbsoluteFile()))
+ if (rootFile.getParentFile()!=null)
+ ITEMS.add(rootFile.getParentFile());
+
+ // Lists all children, optionally display only folders.
+ File[] filesListed = rootFile.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File current, String name) {
+ File file = new File(current, name);
+ if (foldersOnly)
+ return file.isDirectory();
+ if (fileExtensions!=null && file.isFile())
+ return fileExtensions.contains(FilenameUtils.getExtension(name));
+ return true;
+ }
+ });
+
+ // Sort files by name, folder has priority
+ Arrays.sort(filesListed, new Comparator() {
+ @Override
+ public int compare(File file1, File file2) {
+ if (file1.isDirectory() && !file2.isDirectory())
+ return -1;
+ if (!file1.isDirectory() && file2.isDirectory())
+ return 1;
+ return file1.getName().compareTo(file2.getName());
+ }
+ });
+
+ Collections.addAll(ITEMS,filesListed);
+
+ mAdapter = new FileChooserAdapter(getActivity(), ITEMS, rootFile, mListener);
+
+ setHasOptionsMenu(true);
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ if (foldersOnly)
+ inflater.inflate(R.menu.file_chooser,menu);
+ super.onCreateOptionsMenu(menu, inflater);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()){
+ case R.id.action_ok:
+ mListener.onFileSelected(rootFile,true);
+ return true;
+ case R.id.action_add_folder:
+ final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(),R.style.AppCompatAlertDialog);
+ View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_single_edit_text,null);
+ final EditText editText = (EditText) view.findViewById(R.id.editText1);
+ editText.setHint(R.string.Chooser__new_folder_name_hint);
+ builder.setTitle(R.string.Chooser__add_folder);
+ builder.setView(view);
+ builder.setCancelable(true);
+ builder.setPositiveButton(R.string.OK, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialogInterface, int i) {
+ File subDirectory = new File(rootFile,editText.getText().toString());
+ if (subDirectory.mkdir())
+ mListener.onFileSelected(subDirectory,false);
+ }
+ });
+ builder.create().show();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.fragment_filechooser, container, false);
+ mRecyclerView = (RecyclerView) view.findViewById(R.id.file_chooser_recyclerView);
+
+ mRecyclerView.setLayoutManager
+ (new LinearLayoutManager(
+ container.getContext(),
+ LinearLayoutManager.VERTICAL,
+ false));
+ mRecyclerView.setHasFixedSize(true);
+
+ // Set the adapter
+ mRecyclerView.setAdapter(mAdapter);
+
+ // Set the toolbar to have location name
+ getActivity().setTitle(rootFile.getAbsolutePath());
+
+ return view;
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ try {
+ mListener = (OnFileChosen) activity;
+ } catch (ClassCastException e) {
+ throw new ClassCastException(activity.toString()
+ + " must implement OnFileChosen");
+ }
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ mListener = null;
+ }
+
+ /**
+ * This interface must be implemented by activities that contain this
+ * fragment to allow an interaction in this fragment to be communicated
+ * to the activity and potentially other fragments contained in that
+ * activity.
+ *
+ * See the Android Training lesson Communicating with Other Fragments for more information.
+ */
+ public interface OnFileChosen {
+ void onFileSelected(File path, Boolean confirmed);
+ }
+}
diff --git a/app/src/main/java/com/doplgangr/secrecy/fragments/FilesListFragment.java b/app/src/main/java/com/doplgangr/secrecy/fragments/FilesListFragment.java
index b7eb6d9..0b0d51b 100644
--- a/app/src/main/java/com/doplgangr/secrecy/fragments/FilesListFragment.java
+++ b/app/src/main/java/com/doplgangr/secrecy/fragments/FilesListFragment.java
@@ -27,6 +27,7 @@
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.NotificationCompat;
@@ -51,6 +52,7 @@
import com.doplgangr.secrecy.Config;
import com.doplgangr.secrecy.CustomApp;
+import com.doplgangr.secrecy.activities.FileChooserActivity;
import com.doplgangr.secrecy.activities.FilePhotoActivity;
import com.doplgangr.secrecy.activities.FilesActivity;
import com.doplgangr.secrecy.events.AddingFileDoneEvent;
@@ -67,7 +69,6 @@
import com.doplgangr.secrecy.R;
import com.doplgangr.secrecy.utils.Util;
import com.doplgangr.secrecy.adapters.FilesListAdapter;
-import com.ipaulpro.afilechooser.FileChooserActivity;
import java.io.File;
import java.io.FileNotFoundException;
@@ -534,10 +535,6 @@ void addFile() {
FilesActivity.onPauseDecision.startActivity();
} catch (ActivityNotFoundException e) {
intent = new Intent(context, FileChooserActivity.class);
- intent.putStringArrayListExtra(
- FileChooserActivity.EXTRA_FILTER_INCLUDE_EXTENSIONS,
- INCLUDE_EXTENSIONS_LIST);
- intent.putExtra(FileChooserActivity.EXTRA_SELECT_FOLDER, false);
startActivityForResult(intent, REQUEST_CODE);
FilesActivity.onPauseDecision.startActivity();
}
@@ -622,7 +619,10 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
.setOngoing(true);
mBuilder.setProgress(0, 0, true);
mNotifyManager.notify(NotificationID, mBuilder.build());
-
+ //if the result is from our internal file chooser
+ Object fileFromChooser = data.getSerializableExtra(com.doplgangr.secrecy.activities.FileChooserActivity.FILE_SELECTED);
+ if (fileFromChooser !=null)
+ addFileInBackground(secret, Uri.fromFile((File) fileFromChooser));
addFileInBackground(secret, data.getData());
super.onActivityResult(requestCode, resultCode, data);
} else {
diff --git a/app/src/main/java/com/doplgangr/secrecy/fragments/SettingsFragment.java b/app/src/main/java/com/doplgangr/secrecy/fragments/SettingsFragment.java
index bf9b5ff..ed788a7 100644
--- a/app/src/main/java/com/doplgangr/secrecy/fragments/SettingsFragment.java
+++ b/app/src/main/java/com/doplgangr/secrecy/fragments/SettingsFragment.java
@@ -41,7 +41,6 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
@@ -49,20 +48,18 @@
import com.doplgangr.secrecy.Config;
import com.doplgangr.secrecy.CustomApp;
import com.doplgangr.secrecy.R;
+import com.doplgangr.secrecy.activities.FileChooserActivity;
import com.doplgangr.secrecy.utils.Util;
import com.doplgangr.secrecy.filesystem.Storage;
import com.doplgangr.secrecy.premium.PremiumStateHelper;
import com.doplgangr.secrecy.premium.StealthMode;
import com.doplgangr.secrecy.adapters.VaultsListFragment;
-import com.ipaulpro.afilechooser.FileChooserActivity;
-import com.ipaulpro.afilechooser.utils.FileUtils;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Map;
-public class SettingsFragment extends PreferenceFragment {
+public class SettingsFragment extends PreferenceFragment{
private static final int REQUEST_CODE_SET_VAULT_ROOT = 6384;
private static final int REQUEST_CODE_MOVE_VAULT = 2058;
private Context context;
@@ -210,18 +207,7 @@ private void preparePreferenceVaultRoot(){
vault_root.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
- choosePath(new getFileListener() {
- @Override
- public void get(File file) {
- Intent intent = new Intent(context, FileChooserActivity.class);
- intent.putStringArrayListExtra(
- FileChooserActivity.EXTRA_FILTER_INCLUDE_EXTENSIONS,
- INCLUDE_EXTENSIONS_LIST);
- intent.putExtra(FileChooserActivity.PATH, file.getAbsolutePath());
- intent.putExtra(FileChooserActivity.EXTRA_SELECT_FOLDER, true);
- startActivityForResult(intent, REQUEST_CODE_SET_VAULT_ROOT);
- }
- });
+ choosePath();
return true;
}
});
@@ -232,18 +218,7 @@ private void preparePreferenceVaultMove(){
vault_move.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
- choosePath(new getFileListener() {
- @Override
- public void get(File file) {
- Intent intent = new Intent(context, FileChooserActivity.class);
- intent.putStringArrayListExtra(
- FileChooserActivity.EXTRA_FILTER_INCLUDE_EXTENSIONS,
- INCLUDE_EXTENSIONS_LIST);
- intent.putExtra(FileChooserActivity.PATH, file.getAbsolutePath());
- intent.putExtra(FileChooserActivity.EXTRA_SELECT_FOLDER, true);
- startActivityForResult(intent, REQUEST_CODE_MOVE_VAULT);
- }
- });
+ movePath();
return true;
}
});
@@ -359,12 +334,10 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
// If the file selection was successful
if (resultCode == Activity.RESULT_OK) {
if (data != null) {
- // Get the URI of the selected file
- final Uri uri = data.getData();
+ // Get the selected file
+ final File file = (File) data.getSerializableExtra(FileChooserActivity.FILE_SELECTED);
try {
- // Get the file path from the URI
- final String path = FileUtils.getPath(context, uri);
- Storage.setRoot(path);
+ Storage.setRoot(file.getAbsolutePath());
Preference vault_root = findPreference(Config.VAULT_ROOT);
vault_root.setSummary(Storage.getRoot().getAbsolutePath());
} catch (Exception e) {
@@ -376,11 +349,10 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
case REQUEST_CODE_MOVE_VAULT:
if (resultCode == Activity.RESULT_OK) {
if (data != null) {
- // Get the URI of the selected file
- final Uri uri = data.getData();
+ // Get the selected file
+ final File file = (File) data.getSerializableExtra(FileChooserActivity.FILE_SELECTED);
try {
- // Get the file path from the URI
- final String path = FileUtils.getPath(context, uri);
+ final String path = file.getAbsolutePath();
if (path.contains(Storage.getRoot().getAbsolutePath())) {
Util.alert(context,
getString(R.string.Settings__cannot_move_vault),
@@ -450,40 +422,17 @@ void moveStorageRoot(String path, ProgressDialog progressDialog) {
progressDialog.dismiss();
}
- void choosePath(final getFileListener listener) {
- AlertDialog.Builder builderSingle = new AlertDialog.Builder(context);
- builderSingle.setTitle(context.getString(R.string.Settings__select_storage_title));
- final ArrayAdapter arrayAdapter = new ArrayAdapter(
- context,
- R.layout.select_dialog_singlechoice);
- final Map storages = Util.getAllStorageLocations();
- for (String key : storages.keySet()) {
- arrayAdapter.add(key);
- }
- builderSingle.setNegativeButton(R.string.CANCEL,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- }
- }
- );
-
- builderSingle.setAdapter(arrayAdapter,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- String strName = arrayAdapter.getItem(which);
- File file = storages.get(strName);
- listener.get(file);
- }
- }
- );
- builderSingle.show();
+ void choosePath() {
+ Intent intent = new Intent(getActivity(), FileChooserActivity.class);
+ intent.putExtra(FileChooserActivity.FOLDERS_ONLY, true);
+ startActivityForResult(intent, REQUEST_CODE_SET_VAULT_ROOT);
}
- public interface getFileListener {
- void get(File file);
+ void movePath() {
+ Intent intent = new Intent(getActivity(), FileChooserActivity.class);
+ intent.putExtra(FileChooserActivity.FOLDERS_ONLY, true);
+ startActivityForResult(intent, REQUEST_CODE_MOVE_VAULT);
}
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/doplgangr/secrecy/utils/Util.java b/app/src/main/java/com/doplgangr/secrecy/utils/Util.java
index 144573a..f55feca 100644
--- a/app/src/main/java/com/doplgangr/secrecy/utils/Util.java
+++ b/app/src/main/java/com/doplgangr/secrecy/utils/Util.java
@@ -209,6 +209,25 @@ public static Boolean canWrite(java.io.File root) {
}
+ /** Checks whether a directory is truly readable. Since File.canRead()
+ * only checks for file security, it is necessary to try doing a File.listFiles()
+ * to test for real directory access.
+ * @param root Directory root to be checked against
+ * @return True if directory can be read, False if any exception occurs
+ * e.g. the folder is not readable, devices not mounted etc.
+ */
+ public static Boolean canReadDir(java.io.File root) {
+ if (root == null)
+ return false;
+ if (!root.exists())
+ return false;
+ try {
+ return root.canRead() && root.listFiles()!=null;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
public static void openURI(String uri) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(uri));
diff --git a/app/src/main/res/drawable-hdpi/ic_action_done.png b/app/src/main/res/drawable-hdpi/ic_action_done.png
new file mode 100644
index 0000000..f073fc1
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_action_done.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_action_folder.png b/app/src/main/res/drawable-hdpi/ic_action_folder.png
new file mode 100644
index 0000000..ef162d8
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_action_folder.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_action_folder_add.png b/app/src/main/res/drawable-hdpi/ic_action_folder_add.png
new file mode 100644
index 0000000..601f883
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_action_folder_add.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_file.png b/app/src/main/res/drawable-hdpi/ic_file.png
new file mode 100644
index 0000000..410be49
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_file.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_action_done.png b/app/src/main/res/drawable-mdpi/ic_action_done.png
new file mode 100644
index 0000000..c372052
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_action_done.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_action_folder.png b/app/src/main/res/drawable-mdpi/ic_action_folder.png
new file mode 100644
index 0000000..66314e9
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_action_folder.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_action_folder_add.png b/app/src/main/res/drawable-mdpi/ic_action_folder_add.png
new file mode 100644
index 0000000..f6d42f6
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_action_folder_add.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_file.png b/app/src/main/res/drawable-mdpi/ic_file.png
new file mode 100644
index 0000000..15aa037
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_file.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_action_done.png b/app/src/main/res/drawable-xhdpi/ic_action_done.png
new file mode 100644
index 0000000..446c536
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_action_done.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_action_folder.png b/app/src/main/res/drawable-xhdpi/ic_action_folder.png
new file mode 100644
index 0000000..c1da4ab
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_action_folder.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_action_folder_add.png b/app/src/main/res/drawable-xhdpi/ic_action_folder_add.png
new file mode 100644
index 0000000..fd23e94
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_action_folder_add.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_file.png b/app/src/main/res/drawable-xhdpi/ic_file.png
new file mode 100644
index 0000000..622d113
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_file.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_done.png b/app/src/main/res/drawable-xxhdpi/ic_action_done.png
new file mode 100644
index 0000000..444b568
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_action_done.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_folder.png b/app/src/main/res/drawable-xxhdpi/ic_action_folder.png
new file mode 100644
index 0000000..c25bb36
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_action_folder.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_folder_add.png b/app/src/main/res/drawable-xxhdpi/ic_action_folder_add.png
new file mode 100644
index 0000000..c9b3d4e
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_action_folder_add.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_file.png b/app/src/main/res/drawable-xxhdpi/ic_file.png
new file mode 100644
index 0000000..8b20e7c
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_file.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_done.png b/app/src/main/res/drawable-xxxhdpi/ic_action_done.png
new file mode 100644
index 0000000..e359a2f
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_action_done.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_folder.png b/app/src/main/res/drawable-xxxhdpi/ic_action_folder.png
new file mode 100644
index 0000000..b9e8694
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_action_folder.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_folder_add.png b/app/src/main/res/drawable-xxxhdpi/ic_action_folder_add.png
new file mode 100644
index 0000000..a8cce8e
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_action_folder_add.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_file.png b/app/src/main/res/drawable-xxxhdpi/ic_file.png
new file mode 100644
index 0000000..445ad41
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_file.png differ
diff --git a/app/src/main/res/layout/activity_file_chooser.xml b/app/src/main/res/layout/activity_file_chooser.xml
new file mode 100644
index 0000000..05a2c0a
--- /dev/null
+++ b/app/src/main/res/layout/activity_file_chooser.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_single_edit_text.xml b/app/src/main/res/layout/dialog_single_edit_text.xml
new file mode 100644
index 0000000..9de0ec2
--- /dev/null
+++ b/app/src/main/res/layout/dialog_single_edit_text.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_filechooser.xml b/app/src/main/res/layout/fragment_filechooser.xml
new file mode 100644
index 0000000..a01aa3a
--- /dev/null
+++ b/app/src/main/res/layout/fragment_filechooser.xml
@@ -0,0 +1,8 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/listitem_single_line_text.xml b/app/src/main/res/layout/listitem_single_line_text.xml
new file mode 100644
index 0000000..72cacff
--- /dev/null
+++ b/app/src/main/res/layout/listitem_single_line_text.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/file_chooser.xml b/app/src/main/res/menu/file_chooser.xml
new file mode 100644
index 0000000..6067c94
--- /dev/null
+++ b/app/src/main/res/menu/file_chooser.xml
@@ -0,0 +1,20 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/color.xml b/app/src/main/res/values/color.xml
index 9d602aa..4fdd3d2 100644
--- a/app/src/main/res/values/color.xml
+++ b/app/src/main/res/values/color.xml
@@ -20,6 +20,8 @@
@color/quantum_deeporange_A200
@color/quantum_deeporange_A100
@color/quantum_deeporange_A400
+ @color/button_material_light
+ @color/primary_text_default_material_light
#727272
\ No newline at end of file
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index 8036a75..601ad42 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -26,6 +26,12 @@
20sp
56dp
+
+
24dp
+
+ 48dp
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 3ed477e..583e0d7 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -75,6 +75,7 @@
Maximal image size
Performance
Sort files by
+ New Folder Name
- Small
- Medium
diff --git a/app/src/main/res/values/strings_file_handling.xml b/app/src/main/res/values/strings_file_handling.xml
index 2a40cd4..217f7a8 100644
--- a/app/src/main/res/values/strings_file_handling.xml
+++ b/app/src/main/res/values/strings_file_handling.xml
@@ -54,4 +54,5 @@
Restore in Progress
Restore Finished. %s has been restored.
New File Name
+ Add Folder
\ No newline at end of file
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 403f4b1..ee8a4da 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -11,6 +11,8 @@
- @style/ButtonBarButton
+
+
\ No newline at end of file