diff --git a/res/layout/sdscanner_fragment.xml b/res/layout/sdscanner_fragment.xml
new file mode 100644
index 00000000..f2fd31d0
--- /dev/null
+++ b/res/layout/sdscanner_fragment.xml
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/values/translatable.xml b/res/values/translatable.xml
index 2d8e1a79..5806b5f8 100644
--- a/res/values/translatable.xml
+++ b/res/values/translatable.xml
@@ -312,4 +312,5 @@ THE SOFTWARE.
Not yet started.
Ignore updated and deleted files outside of the specified path.
Encountered an error and skipping
+ SD Scanner
diff --git a/res/xml/preference_headers.xml b/res/xml/preference_headers.xml
index 341ee025..87571e24 100644
--- a/res/xml/preference_headers.xml
+++ b/res/xml/preference_headers.xml
@@ -45,6 +45,9 @@ THE SOFTWARE.
+
diff --git a/src/ch/blinkenlights/android/vanilla/SDScannerFragment.java b/src/ch/blinkenlights/android/vanilla/SDScannerFragment.java
new file mode 100644
index 00000000..26854de3
--- /dev/null
+++ b/src/ch/blinkenlights/android/vanilla/SDScannerFragment.java
@@ -0,0 +1,196 @@
+/* SD Scanner - A manual implementation of the SD rescan process, compatible
+ * with Android 4.4
+ *
+ * Copyright (C) 2013-2014 Jeremy Erickson
+ * Copyright (C) 2016 Xiao Bao Clark
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ */
+
+package ch.blinkenlights.android.vanilla;
+
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.os.Environment;
+import android.text.method.ScrollingMovementMethod;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import com.gmail.jerickson314.sdscanner.ScanFragment;
+import com.gmail.jerickson314.sdscanner.UIStringGenerator;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Fragment version of the MainActivity from the SD Scanner app
+ */
+public class SDScannerFragment extends Fragment
+ implements ScanFragment.ScanProgressCallbacks
+{
+ ScanFragment mScanFragment;
+
+ @Override
+ public void updateProgressNum(int progressNum) {
+ ProgressBar progressBar = (ProgressBar)findViewById(R.id.progress_bar);
+ progressBar.setProgress(progressNum);
+ }
+
+ @Override
+ public void updateProgressText(UIStringGenerator progressText) {
+ TextView progressLabel = (TextView)findViewById(R.id.progress_label);
+ progressLabel.setText(progressText.toString(getActivity()));
+ }
+
+ @Override
+ public void updateDebugMessages(UIStringGenerator debugMessages) {
+ TextView debugLabel = (TextView)findViewById(R.id.debug_label);
+ debugLabel.setText(debugMessages.toString(getActivity()));
+ }
+
+ @Override
+ public void updatePath(String path) {
+ EditText pathText = (EditText) findViewById(R.id.path_widget);
+ pathText.setText(path);
+ }
+
+ @Override
+ public void updateStartButtonEnabled(boolean startButtonEnabled) {
+ Button startButton = (Button)findViewById(R.id.start_button);
+ startButton.setEnabled(startButtonEnabled);
+ }
+
+ public void updateRestrictCheckboxChecked(boolean checked) {
+ CheckBox restrictCheckbox = (CheckBox) findViewById(R.id.restrict_checkbox);
+ restrictCheckbox.setChecked(checked);
+ }
+
+ @Override
+ public void signalFinished() {
+
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.sdscanner_fragment, container, false);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ // Setup with values from fragment.
+ updateProgressNum(mScanFragment.getProgressNum());
+ updateProgressText(mScanFragment.getProgressText());
+ updateDebugMessages(mScanFragment.getDebugMessages());
+ updateStartButtonEnabled(mScanFragment.getStartButtonEnabled());
+
+ // Update path from preferences
+ SharedPreferences preferences = getActivity().getPreferences(Context.MODE_PRIVATE);
+ try {
+ updatePath(preferences.getString("path",
+ Environment.getExternalStorageDirectory().getCanonicalPath()));
+ updateRestrictCheckboxChecked(preferences.getBoolean(
+ "restrict_db_scan", false));
+ }
+ catch (IOException Ex) {
+ // Should never happen, but getCanonicalPath() declares the throw.
+ updatePath("");
+ updateRestrictCheckboxChecked(false);
+ }
+
+ // Make debug output scrollable.
+ TextView debugLabel = (TextView)findViewById(R.id.debug_label);
+ debugLabel.setMovementMethod(new ScrollingMovementMethod());
+
+ view.findViewById(R.id.path_button).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ try {
+ defaultButtonPressed(v);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+
+ view.findViewById(R.id.start_button).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ try {
+ startButtonPressed(v);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ FragmentManager fm = getFragmentManager();
+ mScanFragment = (ScanFragment) fm.findFragmentByTag("scan");
+
+ if (mScanFragment == null) {
+ mScanFragment = new ScanFragment();
+ fm.beginTransaction().add(mScanFragment, "scan").commit();
+ }
+ mScanFragment.setScanProgressCallbacks(this);
+ }
+
+ private View findViewById(int viewId) {
+ return getView().findViewById(viewId);
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+
+ // Write setting to preferences
+ EditText pathText = (EditText) findViewById(R.id.path_widget);
+ CheckBox restrictCheckbox = (CheckBox) findViewById(R.id.restrict_checkbox);
+
+ SharedPreferences preferences = getActivity().getPreferences(Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putString("path", pathText.getText().toString());
+ editor.putBoolean("restrict_db_scan", restrictCheckbox.isChecked());
+ editor.commit();
+ }
+
+ public void defaultButtonPressed(View view) throws IOException {
+ updatePath(Environment.getExternalStorageDirectory().getCanonicalPath());
+ }
+
+ public void startButtonPressed(View view) throws IOException {
+ startScan();
+ }
+
+ public void startScan() throws IOException {
+ EditText pathText = (EditText) findViewById(R.id.path_widget);
+ File path = new File(pathText.getText().toString());
+ CheckBox restrictCheckbox = (CheckBox) findViewById(R.id.restrict_checkbox);
+
+ mScanFragment.startScan(path.getCanonicalFile(), restrictCheckbox.isChecked());
+ }
+
+}
diff --git a/src/com/gmail/jerickson314/sdscanner/ScanFragment.java b/src/com/gmail/jerickson314/sdscanner/ScanFragment.java
index 9867d197..53469449 100644
--- a/src/com/gmail/jerickson314/sdscanner/ScanFragment.java
+++ b/src/com/gmail/jerickson314/sdscanner/ScanFragment.java
@@ -165,10 +165,16 @@ public class ScanFragment extends Fragment {
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
- mCallbacks = (ScanProgressCallbacks) activity;
+ if(activity instanceof ScanProgressCallbacks) {
+ mCallbacks = (ScanProgressCallbacks) activity;
+ }
mApplicationContext = activity.getApplicationContext();
}
+ public void setScanProgressCallbacks(ScanProgressCallbacks callbacks) {
+ mCallbacks = callbacks;
+ }
+
public ScanFragment() {
super();