OSDN Git Service

ちょっとだけ、preferenceの準備。
authorMRSa <mrsa@myad.jp>
Sun, 19 May 2019 13:56:57 +0000 (22:56 +0900)
committerMRSa <mrsa@myad.jp>
Sun, 19 May 2019 13:56:57 +0000 (22:56 +0900)
20 files changed:
app/build.gradle
app/src/main/java/net/osdn/gokigen/cameratest/ConfirmationDialog.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/cameratest/IApplicationControl.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/cameratest/MainActivity.java
app/src/main/java/net/osdn/gokigen/cameratest/camtest/CamTest.java
app/src/main/java/net/osdn/gokigen/cameratest/fuji/preference/FujiPreferenceFragment.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/cameratest/fuji/preference/IPreferencePropertyAccessor.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/cameratest/fuji/preference/PowerOffController.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/cameratest/logcat/LogCatExporter.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/cameratest/logcat/LogCatFragment.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/cameratest/logcat/LogCatUpdater.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/cameratest/pages/SectionsPagerAdapter.java
app/src/main/res/drawable/ic_power_settings_new_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_refresh_black_24dp.xml [new file with mode: 0644]
app/src/main/res/menu/debug_view.xml [new file with mode: 0644]
app/src/main/res/menu/menu_main.xml
app/src/main/res/values/arrays.xml [new file with mode: 0644]
app/src/main/res/values/strings.xml
app/src/main/res/values/styles.xml
app/src/main/res/xml/preferences_fuji_x.xml [new file with mode: 0644]

index 856de1d..0db7f5b 100644 (file)
@@ -21,6 +21,7 @@ dependencies {
     implementation fileTree(dir: 'libs', include: ['*.jar'])
     implementation 'androidx.appcompat:appcompat:1.1.0-alpha04'
     implementation 'com.google.android.material:material:1.1.0-alpha06'
+    implementation 'androidx.preference:preference:1.0.0'
     implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
     implementation project(':opencv41')
 }
diff --git a/app/src/main/java/net/osdn/gokigen/cameratest/ConfirmationDialog.java b/app/src/main/java/net/osdn/gokigen/cameratest/ConfirmationDialog.java
new file mode 100644 (file)
index 0000000..6e4b4ab
--- /dev/null
@@ -0,0 +1,99 @@
+package net.osdn.gokigen.cameratest;
+
+import android.content.Context;
+import android.content.DialogInterface;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatDialogFragment;
+
+public class ConfirmationDialog extends AppCompatDialogFragment
+{
+    private Context context = null;
+
+    public static ConfirmationDialog newInstance(Context context)
+    {
+        ConfirmationDialog instance = new ConfirmationDialog();
+        instance.prepare(context);
+
+        return (instance);
+    }
+
+    private void prepare(Context context)
+    {
+        this.context = context;
+    }
+
+    public void show(int titleResId, int messageResId, final Callback callback)
+    {
+        String title = "";
+        String message = "";
+
+        // タイトルとメッセージをのダイアログを表示する
+        if (context != null)
+        {
+            title = context.getString(titleResId);
+            message = context.getString(messageResId);
+        }
+        show(title, message, callback);
+    }
+
+    public void show(String title, String message, final Callback callback)
+    {
+        // 確認ダイアログの生成
+        final AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
+        alertDialog.setTitle(title);
+        alertDialog.setIcon(android.R.drawable.ic_dialog_alert);
+        alertDialog.setMessage(message);
+        alertDialog.setCancelable(true);
+
+        // ボタンを設定する(実行ボタン)
+        alertDialog.setPositiveButton(context.getString(R.string.dialog_positive_execute),
+                new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which)
+                    {
+                        callback.confirm();
+                        dialog.dismiss();
+                    }
+                });
+
+        // ボタンを設定する (キャンセルボタン)
+        alertDialog.setNegativeButton(context.getString(R.string.dialog_negative_cancel),
+                new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which)
+                    {
+                        dialog.cancel();
+                    }
+                });
+
+        // 確認ダイアログを表示する
+        alertDialog.show();
+    }
+
+    public void show(int iconResId, String title, String message)
+    {
+        // 表示イアログの生成
+        final AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
+        alertDialog.setTitle(title);
+        alertDialog.setIcon(iconResId);
+        alertDialog.setMessage(message);
+        alertDialog.setCancelable(true);
+
+        // ボタンを設定する(実行ボタン)
+        alertDialog.setPositiveButton(context.getString(R.string.dialog_positive_execute),
+                new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which)
+                    {
+                        dialog.dismiss();
+                    }
+                });
+
+        // 確認ダイアログを表示する
+        alertDialog.show();
+    }
+
+    // コールバックインタフェース
+    public interface Callback
+    {
+        void confirm();
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/cameratest/IApplicationControl.java b/app/src/main/java/net/osdn/gokigen/cameratest/IApplicationControl.java
new file mode 100644 (file)
index 0000000..434a668
--- /dev/null
@@ -0,0 +1,7 @@
+package net.osdn.gokigen.cameratest;
+
+public interface IApplicationControl
+{
+    void exitApplication();
+
+}
index 4265b7c..59b1b11 100644 (file)
@@ -27,7 +27,7 @@ import net.osdn.gokigen.cameratest.pages.SectionsPagerAdapter;
 import org.opencv.android.BaseLoaderCallback;
 import org.opencv.android.LoaderCallbackInterface;
 
-public class MainActivity extends AppCompatActivity
+public class MainActivity extends AppCompatActivity implements IApplicationControl
 {
     /////// OpenCV ///////  : license https://opencv.org/license/
     static
@@ -77,7 +77,7 @@ public class MainActivity extends AppCompatActivity
 
         // Create the adapter that will return a fragment for each of the three
         // primary sections of the activity.
-        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager(), testTarget);
+        mSectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager(), testTarget, this);
 
         // Set up the ViewPager with the sections adapter.
         mViewPager = findViewById(R.id.container);
@@ -173,13 +173,12 @@ public class MainActivity extends AppCompatActivity
             testTarget.disconnect();
             return (true);
         }
+/*
         if (id == R.id.action_settings)
         {
             testTarget.settings();
             return (true);
         }
-
-/*
         if (id == R.id.action_reset)
         {
             testTarget.resetConnection();
@@ -250,7 +249,8 @@ public class MainActivity extends AppCompatActivity
     /**
      *
      */
-    private void exitApplication()
+    @Override
+    public void exitApplication()
     {
         try
         {
index 68a77b8..6b28353 100644 (file)
@@ -14,6 +14,7 @@ import com.google.android.material.snackbar.Snackbar;
 
 import net.osdn.gokigen.cameratest.R;
 import net.osdn.gokigen.cameratest.fuji.Connection;
+import net.osdn.gokigen.cameratest.fuji.preference.FujiPreferenceFragment;
 import net.osdn.gokigen.cameratest.fuji.ILiveViewImage;
 import net.osdn.gokigen.cameratest.fuji.ReceivedDataHolder;
 import net.osdn.gokigen.cameratest.fuji.statuses.IFujiStatus;
@@ -27,6 +28,8 @@ public class CamTest implements View.OnClickListener, View.OnTouchListener, ILiv
     private final Activity activity;
     private TextView textview;
     private Connection connection;
+
+    private FujiPreferenceFragment preferenceFragment = null;
     //private FileOutputStream outputStream = null;
     private static final int offsetSize = 18;  // 4byte: データサイズ、14byte: (謎の)ヘッダ
 
@@ -113,14 +116,25 @@ public class CamTest implements View.OnClickListener, View.OnTouchListener, ILiv
         }
     }
 
+/*
     public void settings()
     {
         Log.v(TAG, "Show settings menu");
 
+        if (preferenceFragment == null)
+        {
+            preferenceFragment = FujiPreferenceFragment.newInstance();
+        }
+        FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
+        transaction.replace(R.id.fragment1, logCatFragment);
+        // backstackに追加
+        transaction.addToBackStack(null);
+        transaction.commit();
+
+
         showMessageText("BBBB");
     }
 
-/*
     public void valueUp()
     {
         Log.v(TAG, "value UP");
diff --git a/app/src/main/java/net/osdn/gokigen/cameratest/fuji/preference/FujiPreferenceFragment.java b/app/src/main/java/net/osdn/gokigen/cameratest/fuji/preference/FujiPreferenceFragment.java
new file mode 100644 (file)
index 0000000..d1fc3c4
--- /dev/null
@@ -0,0 +1,59 @@
+package net.osdn.gokigen.cameratest.fuji.preference;
+
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragmentCompat;
+
+import net.osdn.gokigen.cameratest.IApplicationControl;
+import net.osdn.gokigen.cameratest.R;
+
+public class FujiPreferenceFragment extends PreferenceFragmentCompat
+{
+    private PowerOffController powerOffController = null;
+
+    /**
+     *
+     *
+     */
+    public static FujiPreferenceFragment newInstance(@NonNull Context context, @NonNull IApplicationControl control)
+    {
+        FujiPreferenceFragment instance = new FujiPreferenceFragment();
+        instance.prepare(context, control);
+
+        // パラメータはBundleにまとめておく
+        Bundle arguments = new Bundle();
+        //arguments.putString("title", title);
+        //arguments.putString("message", message);
+        instance.setArguments(arguments);
+
+        return (instance);
+    }
+
+    private void prepare(@NonNull Context context, @NonNull IApplicationControl control)
+    {
+        powerOffController = new PowerOffController(context, control);
+    }
+
+    @Override
+    public void onCreatePreferences(Bundle savedInstanceState, String rootKey)
+    {
+        setPreferencesFromResource(R.xml.preferences_fuji_x, rootKey);
+
+        ListPreference connectionMethod = (ListPreference) findPreference(IPreferencePropertyAccessor.CONNECTION_METHOD);
+        connectionMethod.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+            @Override
+            public boolean onPreferenceChange(Preference preference, Object newValue) {
+                preference.setSummary(newValue + " ");
+                return (true);
+            }
+        });
+        connectionMethod.setSummary(connectionMethod.getValue() + " ");
+
+        findPreference("exit_application").setOnPreferenceClickListener(powerOffController);
+
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/cameratest/fuji/preference/IPreferencePropertyAccessor.java b/app/src/main/java/net/osdn/gokigen/cameratest/fuji/preference/IPreferencePropertyAccessor.java
new file mode 100644 (file)
index 0000000..54f3f60
--- /dev/null
@@ -0,0 +1,10 @@
+package net.osdn.gokigen.cameratest.fuji.preference;
+
+public interface IPreferencePropertyAccessor
+{
+    String EXIT_APPLICATION = "exit_application";
+    String CONNECTION_METHOD = "connection_method";
+    String CONNECTION_METHOD_DEFAULT_VALUE = "FUJI_X";
+
+
+}
diff --git a/app/src/main/java/net/osdn/gokigen/cameratest/fuji/preference/PowerOffController.java b/app/src/main/java/net/osdn/gokigen/cameratest/fuji/preference/PowerOffController.java
new file mode 100644 (file)
index 0000000..859604f
--- /dev/null
@@ -0,0 +1,65 @@
+package net.osdn.gokigen.cameratest.fuji.preference;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.preference.Preference;
+
+import net.osdn.gokigen.cameratest.ConfirmationDialog;
+import net.osdn.gokigen.cameratest.IApplicationControl;
+import net.osdn.gokigen.cameratest.R;
+
+public class PowerOffController implements Preference.OnPreferenceClickListener, ConfirmationDialog.Callback
+{
+    private final Context context;
+    private final IApplicationControl appControl;
+    private String preferenceKey = null;
+
+    PowerOffController(@NonNull Context context, @NonNull IApplicationControl control)
+    {
+        this.context = context;
+        this.appControl = control;
+    }
+
+    @Override
+    public boolean onPreferenceClick(Preference preference)
+    {
+        if (!preference.hasKey())
+        {
+            return (false);
+        }
+
+        preferenceKey = preference.getKey();
+        if (preferenceKey.contains(IPreferencePropertyAccessor.EXIT_APPLICATION))
+        {
+
+            // 確認ダイアログの生成と表示
+            ConfirmationDialog dialog = ConfirmationDialog.newInstance(context);
+            dialog.show(R.string.dialog_title_confirmation, R.string.dialog_message_power_off, this);
+            return (true);
+        }
+        return (false);
+    }
+
+    /**
+     *
+     *
+     */
+    @Override
+    public void confirm()
+    {
+        try
+        {
+            if (preferenceKey.contains(IPreferencePropertyAccessor.EXIT_APPLICATION))
+            {
+                // カメラの電源をOFFにしたうえで、アプリケーションを終了する。
+                appControl.exitApplication();
+
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/cameratest/logcat/LogCatExporter.java b/app/src/main/java/net/osdn/gokigen/cameratest/logcat/LogCatExporter.java
new file mode 100644 (file)
index 0000000..0830eca
--- /dev/null
@@ -0,0 +1,64 @@
+package net.osdn.gokigen.cameratest.logcat;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.util.Log;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+
+import androidx.annotation.NonNull;
+
+import net.osdn.gokigen.cameratest.ConfirmationDialog;
+import net.osdn.gokigen.cameratest.R;
+
+class LogCatExporter implements AdapterView.OnItemLongClickListener
+{
+    private final String TAG = toString();
+    private final Activity activity;
+
+    LogCatExporter(@NonNull Activity context)
+    {
+        this.activity = context;
+
+    }
+
+    @Override
+    public boolean onItemLongClick(final AdapterView<?> adapterView, View view, int i, long l)
+    {
+        Log.v(TAG, "onItemLongClick()" );
+
+        ConfirmationDialog confirm = ConfirmationDialog.newInstance(activity);
+
+        confirm.show(R.string.dialog_confirm_title_output_log, R.string.dialog_confirm_message_output_log, new ConfirmationDialog.Callback() {
+            @Override
+            public void confirm()
+            {
+                Log.v(TAG, "confirm()" );
+                try {
+                    StringBuilder buf = new StringBuilder();
+                    ArrayAdapter<String> adapter = (ArrayAdapter<String>) adapterView.getAdapter();
+                    for (int index = 0; index < adapter.getCount(); index++)
+                    {
+                        buf.append(adapter.getItem(index));
+                        buf.append("\r\n");
+                    }
+
+                    Intent intent = new Intent();
+                    intent.setAction(Intent.ACTION_SEND);
+                    intent.setType("text/plain");
+                    intent.putExtra(Intent.EXTRA_TITLE, "debug log for " + activity.getString(R.string.app_name));
+                    intent.putExtra(Intent.EXTRA_TEXT, new String(buf));
+                    activity.startActivity(intent);
+
+                    // Toast.makeText(activity, adapter.getItem(adapter.getCount() - 1), Toast.LENGTH_SHORT).show();
+                }
+                catch (Exception e)
+                {
+                    e.printStackTrace();
+                }
+            }
+        });
+        return (true);
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/cameratest/logcat/LogCatFragment.java b/app/src/main/java/net/osdn/gokigen/cameratest/logcat/LogCatFragment.java
new file mode 100644 (file)
index 0000000..d5df593
--- /dev/null
@@ -0,0 +1,198 @@
+package net.osdn.gokigen.cameratest.logcat;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+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.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.Toast;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.annotation.Nullable;
+import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.ListFragment;
+
+import net.osdn.gokigen.cameratest.R;
+
+/**
+ *
+ */
+public class LogCatFragment extends ListFragment
+{
+    private final String TAG = toString();
+    private ArrayAdapter<String> adapter;
+    private List<String> dataItems = new ArrayList<>();
+    private LogCatUpdater updater = new LogCatUpdater();
+    public static LogCatFragment newInstance()
+    {
+        LogCatFragment instance = new LogCatFragment();
+
+        // パラメータはBundleにまとめておく
+        Bundle arguments = new Bundle();
+        //arguments.putString("title", title);
+        //arguments.putString("message", message);
+        instance.setArguments(arguments);
+
+        //instance.prepare();
+        return (instance);
+    }
+
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
+    {
+        inflater.inflate(R.menu.debug_view, menu);
+/*
+        String title = getString(R.string.app_name) + " " + getString(R.string.pref_degug_info);
+        try {
+            AppCompatActivity activity = (AppCompatActivity) getActivity();
+            ActionBar bar = activity.getSupportActionBar();
+            if (bar != null)
+            {
+                bar.setTitle(title);
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+*/
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item)
+    {
+        if (item.getItemId() == R.id.action_refresh)
+        {
+            update();
+            return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    /**
+     *   表示データの更新
+     *
+     */
+    private void update()
+    {
+        dataItems.clear();
+        Thread thread = new Thread(new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                Log.v(TAG, "START LOGCAT");
+                dataItems = updater.getLogCat("main", "time", "*:v", "gokigen", "");
+                Log.v(TAG, "FINISH LOGCAT");
+                try
+                {
+                    final FragmentActivity activity = getActivity();
+                    if (activity != null)
+                    {
+                        activity.runOnUiThread(new Runnable()
+                        {
+                            @Override
+                            public void run()
+                            {
+                                try
+                                {
+                                    // 中身があったらクリアする
+                                    if (adapter.getCount() > 0)
+                                    {
+                                        adapter.clear();
+                                    }
+
+                                    // リストの内容を更新する
+                                    adapter.addAll(dataItems);
+
+                                    // 最下部にカーソルを移したい
+                                    ListView view = activity.findViewById(android.R.id.list);
+                                    view.setSelection(dataItems.size());
+
+                                    // 更新終了通知
+                                    //Snackbar.make(getActivity().findViewById(R.id.fragment1), getString(R.string.finish_refresh), Snackbar.LENGTH_SHORT).show();
+                                    Toast.makeText(getActivity(), getString(R.string.finish_refresh), Toast.LENGTH_SHORT).show();
+                                }
+                                catch (Exception ee)
+                                {
+                                    ee.printStackTrace();
+                                }
+                            }
+                        });
+                    }
+                }
+                catch (Exception e)
+                {
+                    e.printStackTrace();
+                }
+            }
+        });
+        try
+        {
+            // 本当は、ここでダイアログを出したい
+            thread.start();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void onResume()
+    {
+        super.onResume();
+        Log.v(TAG, "onResume()");
+
+        update();
+    }
+
+    @Override
+    public void onPause()
+    {
+        super.onPause();
+        Log.v(TAG, "onPause()");
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState)
+    {
+        super.onCreate(savedInstanceState);
+        Log.v(TAG, "LogCatFragment::onCreate()");
+    }
+
+    @Override
+    public void onActivityCreated(@Nullable Bundle savedInstanceState)
+    {
+        super.onActivityCreated(savedInstanceState);
+        Log.v(TAG, "LogCatFragment::onActivityCreated()");
+        setHasOptionsMenu(true);
+
+        Activity activity = getActivity();
+        if (activity != null)
+        {
+            ListView view = getListView();
+            if (view != null)
+            {
+                getListView().setOnItemLongClickListener(new LogCatExporter(activity));
+            }
+        }
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
+    {
+        adapter = new ArrayAdapter<>(inflater.getContext(), android.R.layout.simple_list_item_1, dataItems);
+        setListAdapter(adapter);
+
+        return (super.onCreateView(inflater, container, savedInstanceState));
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/cameratest/logcat/LogCatUpdater.java b/app/src/main/java/net/osdn/gokigen/cameratest/logcat/LogCatUpdater.java
new file mode 100644 (file)
index 0000000..46bfe79
--- /dev/null
@@ -0,0 +1,69 @@
+package net.osdn.gokigen.cameratest.logcat;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+class LogCatUpdater
+{
+    LogCatUpdater()
+    {
+        //
+    }
+
+    /**
+     *
+     * @param ringbuffer : main - メイン ログバッファ, radio - 無線通信や電話に関連するメッセージが含まれるバッファ, events - イベントに関連するメッセージが含まれるバッファ
+     * @param logFormat : brief - 優先度 / タグとメッセージ発行元プロセスの PID, process - PID のみ, tag - 優先度 / タグのみ, raw - 生のログ, time - 日付、起動時刻、優先度 / タグ、メッセージ発行元プロセスの PID , threadtime - 日付、起動時刻、優先度、タグ、メッセージ発行元スレッドの PID および TID, long - すべてのメタデータ フィールド
+     * @param filterSpec :  レベル : SFEWIDV
+     * @param filterString : 指定した文字列がログに含まれている場合に表示
+     * @param filterRegEx :  指定した正規表現の文字列がログに含まれている場合に表示
+     * @return ログのリスト
+     */
+
+    List<String> getLogCat(String ringbuffer, String logFormat, String filterSpec, String filterString, String filterRegEx)
+    {
+        final int BUFFER_SIZE = 8192;
+        ArrayList<String> listItems = new ArrayList<String>();
+        try
+        {
+            ArrayList<String> commandLine = new ArrayList<String>();
+            commandLine.add("logcat");
+            commandLine.add("-d");       //  -d:  dump the log and then exit (don't block)
+            commandLine.add("-b");       //  -b <buffer> : request alternate ring buffer ('main' (default), 'radio', 'events')
+            commandLine.add(ringbuffer);  //     <buffer> option.
+            commandLine.add("-v");       //  -v <format> :  Sets the log print format, where <format> is one of:
+            commandLine.add(logFormat);   //                 brief process tag thread raw time threadtime long
+            commandLine.add(filterSpec);  //
+            Process process = Runtime.getRuntime().exec(commandLine.toArray(new String[commandLine.size()]));
+
+            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()), BUFFER_SIZE);
+            String line;
+            do
+            {
+                line = bufferedReader.readLine();
+                try
+                {
+                    int filterLength = filterString.length();
+                    int filterRegExLength = filterRegEx.length();
+                    if (((filterLength == 0)&&(filterRegExLength == 0))||
+                            ((filterLength > 0)&&(line.contains(filterString)))||
+                            ((filterRegExLength > 0)&&(line.matches(filterRegEx))))
+                    {
+                        listItems.add(line);
+                    }
+                }
+                catch (Exception ee)
+                {
+                    ee.printStackTrace();
+                }
+            } while (line != null);
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        return (listItems);
+    }
+}
index ec0b71d..3e8a94d 100644 (file)
@@ -1,7 +1,13 @@
 package net.osdn.gokigen.cameratest.pages;
 
+import android.content.Context;
+
+import net.osdn.gokigen.cameratest.IApplicationControl;
 import net.osdn.gokigen.cameratest.camtest.CamTest;
+import net.osdn.gokigen.cameratest.fuji.preference.FujiPreferenceFragment;
+import net.osdn.gokigen.cameratest.logcat.LogCatFragment;
 
+import androidx.annotation.NonNull;
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentManager;
 import androidx.fragment.app.FragmentPagerAdapter;
@@ -12,25 +18,49 @@ import androidx.fragment.app.FragmentPagerAdapter;
  */
 public class SectionsPagerAdapter extends FragmentPagerAdapter
 {
+    private final Context context;
     private final CamTest testTarget;
-    public SectionsPagerAdapter(FragmentManager fm, CamTest testTarget)
+    private final IApplicationControl appControl;
+    private LogCatFragment logCatFragment = null;
+    private FujiPreferenceFragment preferenceFragment = null;
+    private TestViewFragment testViewFragment = null;
+    public SectionsPagerAdapter(@NonNull Context context, FragmentManager fm, CamTest testTarget, IApplicationControl control)
     {
         super(fm);
+        this.context = context;
         this.testTarget = testTarget;
+        this.appControl = control;
     }
 
     @Override
-    public Fragment getItem(int position)
+    public @NonNull Fragment getItem(int position)
     {
-        // getItem is called to instantiate the fragment for the given page.
-        // Return a TestViewFragment (defined as a static inner class below).
-        return TestViewFragment.newInstance((position + 1), testTarget);
+        if (position == 2)
+        {
+            if (logCatFragment == null)
+            {
+                logCatFragment = LogCatFragment.newInstance();
+            }
+            return (logCatFragment);
+        }
+        else if (position == 1)
+        {
+            if (preferenceFragment == null)
+            {
+                preferenceFragment = FujiPreferenceFragment.newInstance(context, appControl);
+            }
+            return (preferenceFragment);
+        }
+        if (testViewFragment == null)
+        {
+            testViewFragment = TestViewFragment.newInstance((position + 1), testTarget);
+        }
+        return (testViewFragment);
     }
 
     @Override
     public int getCount()
     {
-        // Show only one page.
-        return 1;
+        return 3;
     }
 }
diff --git a/app/src/main/res/drawable/ic_power_settings_new_black_24dp.xml b/app/src/main/res/drawable/ic_power_settings_new_black_24dp.xml
new file mode 100644 (file)
index 0000000..26272ab
--- /dev/null
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M13,3h-2v10h2L13,3zM17.83,5.17l-1.42,1.42C17.99,7.86 19,9.81 19,12c0,3.87 -3.13,7 -7,7s-7,-3.13 -7,-7c0,-2.19 1.01,-4.14 2.58,-5.42L6.17,5.17C4.23,6.82 3,9.26 3,12c0,4.97 4.03,9 9,9s9,-4.03 9,-9c0,-2.74 -1.23,-5.18 -3.17,-6.83z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_refresh_black_24dp.xml b/app/src/main/res/drawable/ic_refresh_black_24dp.xml
new file mode 100644 (file)
index 0000000..8229a9a
--- /dev/null
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z"/>
+</vector>
diff --git a/app/src/main/res/menu/debug_view.xml b/app/src/main/res/menu/debug_view.xml
new file mode 100644 (file)
index 0000000..731369b
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+       xmlns:compat="http://schemas.android.com/apk/res-auto" >
+
+    <item
+        android:id="@+id/action_refresh"
+        compat:showAsAction="always"
+        android:icon="@drawable/ic_refresh_black_24dp"
+        android:title="@string/action_refresh"
+        android:visible="true" />
+
+</menu>
index 3f56b52..412e244 100644 (file)
         android:orderInCategory="100"
         android:title="@string/action_wifi_settings"
         app:showAsAction="never" />
-    <item
-        android:id="@+id/action_settings"
-        android:orderInCategory="100"
-        android:title="@string/action_settings"
-        app:showAsAction="never" />
+
     <item
         android:id="@+id/action_disconnect"
         android:orderInCategory="100"
 
 <!--
     <item
+        android:id="@+id/action_settings"
+        android:orderInCategory="100"
+        android:title="@string/action_settings"
+        app:showAsAction="never" />
+
+    <item
         android:id="@+id/action_reset"
         android:orderInCategory="100"
         android:title="@string/action_reset"
@@ -35,6 +37,7 @@
         android:orderInCategory="100"
         android:title="@string/action_up"
         app:showAsAction="never" />
+
     <item
         android:id="@+id/action_down_value"
         android:orderInCategory="100"
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
new file mode 100644 (file)
index 0000000..91781b3
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string-array name="connection_method">
+        <item>Fuji X Series</item>
+        <item>Ricoh GR II / PENTAX DSLR</item>
+        <item>OPC(Olympus Air)</item>
+    </string-array>
+
+    <string-array name="connection_method_value">
+        <item>FUJI_X</item>
+        <item>RICOH_GR2</item>
+        <item>OPC</item>
+    </string-array>
+
+</resources>
index 0450647..f8b2244 100644 (file)
     <string name="action_down">Down</string>
     <string name="action_reset">Reset Connection</string>
     <string name="action_disconnect">Disconnect</string>
+
+    <string name="pref_cat_application_control">App. Control</string>
+    <string name="pref_exit_power_off">Exit Application(and Camera OFF)</string>
+    <string name="pref_connection_method">Connection Method</string>
+    <string name="pref_cat_camera">Camera</string>
+    <string name="pref_capture_both_camera_and_live_view">Capture both camera and Live View</string>
+
+    <string name="pref_cat_others">Others</string>
+
+    <string name="pref_cat_gokigen">GOKIGEN</string>
+    <string name="pref_instruction_manual">Instructions</string>
+    <string name="pref_privacy_policy">Privacy Policy</string>
+
+    <string name="pref_degug_info">Debug Information</string>
+    <string name="pref_summary_debug_info">LogCat Information</string>
+
+
+    <string name="dialog_title_confirmation">Confirmation</string>
+    <string name="dialog_positive_execute">OK</string>
+    <string name="dialog_negative_cancel">Cancel</string>
+
+    <string name="dialog_confirm_title_output_log">Share debug log</string>
+    <string name="dialog_confirm_message_output_log">Share the debug log, OK?</string>
+
+    <string name="action_refresh">Refresh</string>
+    <string name="finish_refresh">Finished Refresh</string>
+
+    <string name="dialog_message_power_off">Power Off</string>
+
 </resources>
index 545b9c6..7a78279 100644 (file)
@@ -6,6 +6,7 @@
         <item name="colorPrimary">@color/colorPrimary</item>
         <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
         <item name="colorAccent">@color/colorAccent</item>
+        <item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
     </style>
 
     <style name="AppTheme.NoActionBar">
diff --git a/app/src/main/res/xml/preferences_fuji_x.xml b/app/src/main/res/xml/preferences_fuji_x.xml
new file mode 100644 (file)
index 0000000..30c2483
--- /dev/null
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
+    <PreferenceCategory
+        android:title="@string/pref_cat_application_control">
+
+        <PreferenceScreen
+            android:key="exit_application"
+            android:icon="@drawable/ic_power_settings_new_black_24dp"
+            android:title="@string/pref_exit_power_off" />
+
+        <ListPreference
+            android:title="@string/pref_connection_method"
+            android:entryValues="@array/connection_method_value"
+            android:entries="@array/connection_method"
+            android:key="connection_method"
+            android:defaultValue="RICOH_GR2"/>
+
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:title="@string/pref_cat_camera">
+
+        <CheckBoxPreference
+            android:key="capture_both_camera_and_live_view"
+            android:title="@string/pref_capture_both_camera_and_live_view" />
+
+    </PreferenceCategory>
+
+
+    <PreferenceCategory
+        android:title="@string/pref_cat_others">
+
+
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:title="@string/pref_cat_gokigen">
+
+        <Preference
+            android:key="instruction_link"
+            android:title="@string/pref_instruction_manual"
+            android:summary="https://osdn.net/projects/gokigen/wiki/GR2Control"
+            android:selectable="true">
+            <intent android:action="android.intent.action.VIEW"
+                android:data="https://osdn.net/projects/gokigen/wiki/GR2Control" />
+        </Preference>
+
+        <Preference
+            android:key="privacy_policy"
+            android:title="@string/pref_privacy_policy"
+            android:summary="https://osdn.net/projects/gokigen/wiki/PrivacyPolicy"
+            android:selectable="true">
+            <intent android:action="android.intent.action.VIEW"
+                android:data="https://osdn.net/projects/gokigen/wiki/PrivacyPolicy" />
+        </Preference>
+
+    </PreferenceCategory>
+</PreferenceScreen>