OSDN Git Service

デバッグログ(logcat)の表示機能を追加してみる。
authorMRSa <mrsa@myad.jp>
Thu, 28 Dec 2017 14:33:12 +0000 (23:33 +0900)
committerMRSa <mrsa@myad.jp>
Thu, 28 Dec 2017 14:33:12 +0000 (23:33 +0900)
app/src/main/java/net/osdn/gokigen/a01d/A01dMain.java
app/src/main/java/net/osdn/gokigen/a01d/IChangeScene.java
app/src/main/java/net/osdn/gokigen/a01d/logcat/LogCatFragment.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/logcat/LogCatUpdater.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/logcat/LogCatViewer.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/preference/PreferenceFragment.java
app/src/main/res/menu/debug_view.xml [new file with mode: 0644]
app/src/main/res/values-ja/strings.xml
app/src/main/res/values/strings.xml
app/src/main/res/xml/preferences.xml

index 8dd3a17..86522a5 100644 (file)
@@ -23,6 +23,7 @@ import net.osdn.gokigen.a01d.camera.olympus.wrapper.connection.IOlyCameraConnect
 import net.osdn.gokigen.a01d.camera.olympus.wrapper.connection.ble.ICameraPowerOn;
 import net.osdn.gokigen.a01d.liveview.IStatusViewDrawer;
 import net.osdn.gokigen.a01d.liveview.LiveViewFragment;
+import net.osdn.gokigen.a01d.logcat.LogCatFragment;
 import net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor;
 import net.osdn.gokigen.a01d.preference.PreferenceFragment;
 
@@ -39,6 +40,7 @@ public class A01dMain extends AppCompatActivity implements ICameraStatusReceiver
 
     private PreferenceFragment preferenceFragment = null;
     private OlyCameraPropertyListFragment propertyListFragment = null;
+    private LogCatFragment logCatFragment = null;
 
     @Override
     protected void onCreate(Bundle savedInstanceState)
@@ -230,6 +232,26 @@ public class A01dMain extends AppCompatActivity implements ICameraStatusReceiver
     }
 
     /**
+     *   デバッグ情報画面を開く
+     *
+     */
+    @Override
+    public void changeSceneToDebugInformation()
+    {
+        if (logCatFragment == null)
+        {
+            logCatFragment = LogCatFragment.newInstance();
+        }
+        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+        transaction.replace(R.id.fragment1, logCatFragment);
+        // backstackに追加
+        transaction.addToBackStack(null);
+        transaction.commit();
+    }
+
+
+
+    /**
      *   カメラとの接続・切断のシーケンス
      */
     @Override
index 49298ca..1558095 100644 (file)
@@ -8,5 +8,6 @@ public interface IChangeScene
     void changeSceneToCameraPropertyList();
     void changeSceneToConfiguration();
     void changeCameraConnection();
+    void changeSceneToDebugInformation();
     void exitApplication();
 }
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/logcat/LogCatFragment.java b/app/src/main/java/net/osdn/gokigen/a01d/logcat/LogCatFragment.java
new file mode 100644 (file)
index 0000000..533a0d3
--- /dev/null
@@ -0,0 +1,184 @@
+package net.osdn.gokigen.a01d.logcat;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.ListFragment;
+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 net.osdn.gokigen.a01d.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ */
+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());
+
+                                    // 更新終了通知
+                                    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);
+    }
+
+    @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/a01d/logcat/LogCatUpdater.java b/app/src/main/java/net/osdn/gokigen/a01d/logcat/LogCatUpdater.java
new file mode 100644 (file)
index 0000000..57cc0d3
--- /dev/null
@@ -0,0 +1,70 @@
+package net.osdn.gokigen.a01d.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 = null;
+            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);
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/logcat/LogCatViewer.java b/app/src/main/java/net/osdn/gokigen/a01d/logcat/LogCatViewer.java
new file mode 100644 (file)
index 0000000..91db174
--- /dev/null
@@ -0,0 +1,48 @@
+package net.osdn.gokigen.a01d.logcat;
+
+import android.support.v7.preference.Preference;
+import android.util.Log;
+
+import net.osdn.gokigen.a01d.IChangeScene;
+
+public class LogCatViewer implements android.support.v7.preference.Preference.OnPreferenceClickListener
+{
+    private final String TAG = toString();
+    private final IChangeScene changeScene;
+    //private String preferenceKey = null;
+
+    public LogCatViewer(IChangeScene changeScene)
+    {
+        this.changeScene = changeScene;
+    }
+
+    public void prepare()
+    {
+        Log.v(TAG, "prepare() ");
+    }
+
+    @Override
+    public boolean onPreferenceClick(Preference preference)
+    {
+        if (!preference.hasKey())
+        {
+            return (false);
+        }
+
+        String preferenceKey = preference.getKey();
+        if ((preferenceKey.contains("debug_info"))&&(changeScene != null))
+        {
+            try
+            {
+                // デバッグ情報を表示する
+                changeScene.changeSceneToDebugInformation();
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+            }
+            return (true);
+        }
+        return (false);
+    }
+}
index 256ac9c..f0eaa08 100644 (file)
@@ -22,6 +22,7 @@ import net.osdn.gokigen.a01d.camera.olympus.wrapper.property.IOlyCameraProperty;
 import net.osdn.gokigen.a01d.camera.olympus.wrapper.property.IOlyCameraPropertyProvider;
 import net.osdn.gokigen.a01d.camera.olympus.IOlympusInterfaceProvider;
 import net.osdn.gokigen.a01d.camera.olympus.operation.CameraPowerOff;
+import net.osdn.gokigen.a01d.logcat.LogCatViewer;
 
 import java.util.HashMap;
 import java.util.Locale;
@@ -42,6 +43,7 @@ public class PreferenceFragment extends PreferenceFragmentCompat implements Shar
     private ICameraRunMode changeRunModeExecutor = null;
     private CameraPowerOff powerOffController = null;
     private OlyCameraPowerOnSelector powerOnSelector = null;
+    private LogCatViewer logCatViewer = null;
     private SharedPreferences preferences = null;
     private ProgressDialog busyDialog = null;
     private PreferenceSynchronizer preferenceSynchronizer = null;
@@ -60,6 +62,8 @@ public class PreferenceFragment extends PreferenceFragmentCompat implements Shar
         powerOffController.prepare();
         powerOnSelector = new OlyCameraPowerOnSelector(context);
         powerOnSelector.prepare();
+        logCatViewer = new LogCatViewer(changeScene);
+        logCatViewer.prepare();
     }
 
     /**
@@ -203,6 +207,7 @@ public class PreferenceFragment extends PreferenceFragmentCompat implements Shar
         }
         findPreference("exit_application").setOnPreferenceClickListener(powerOffController);
         findPreference("olympus_air_bt").setOnPreferenceClickListener(powerOnSelector);
+        findPreference("debug_info").setOnPreferenceClickListener(logCatViewer);
     }
 
     /**
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 9e469ca..be5160e 100644 (file)
@@ -71,6 +71,9 @@
     <string name="pref_summary_air_bt">Olympus AIRの設定を登録します。</string>
     <string name="saved_my_camera">登録しました : </string>
 
+    <string name="pref_degug_info">デバッグ情報</string>
+    <string name="pref_summary_debug_info">調査用の情報を表示します</string>
+
     <string name="auto_save_props">(自動保存)</string>
     <string name="title_tab_title_load">設定反映</string>
     <string name="title_tab_title_save">設定保存</string>
@@ -94,4 +97,8 @@
     <string name="fatal_cannot_use_camera">Olympus Camera Kitが動作しないモードのため、カメラのリセットが必要です。電源ボタンを8秒以上長押しして、カメラをリセットしてください。</string>
     <string name="network_connection_timeout">接続タイムアウト</string>
     <string name="restored_my_props">設定を展開しました。 : </string>
+
+    <string name="action_refresh">更新</string>
+    <string name="finish_refresh">更新終了</string>
+
 </resources>
index 8a8da73..8ec0bb6 100644 (file)
@@ -82,6 +82,9 @@
     <string name="pref_summary_air_bt">Entry your Olympus Air</string>
     <string name="saved_my_camera">Registerd : </string>
 
+    <string name="pref_degug_info">Debug Information</string>
+    <string name="pref_summary_debug_info">LogCat Information</string>
+
     <string name="connect_start">start</string>
     <string name="connect_check_wifi">check WIFI</string>
     <string name="connect_connect">connecting</string>
     <string name="dialog_start_load_property_title">Setting Properties&#8230;</string>
     <string name="restored_my_props">Restored Property : </string>
 
+    <string name="action_refresh">Refresh</string>
+    <string name="finish_refresh">Finished Refresh</string>
 </resources>
index d4fe4cb..286abf2 100644 (file)
 
     <PreferenceCategory
         android:title="@string/pref_cat_gokigen">
+
         <Preference
             android:key="instruction_link"
             android:title="@string/pref_instruction_manual"
             <intent android:action="android.intent.action.VIEW"
                 android:data="https://osdn.net/projects/gokigen/wiki/A01d" />
         </Preference>
+
         <Preference
             android:key="privacy_policy"
             android:title="@string/pref_privacy_policy"
             <intent android:action="android.intent.action.VIEW"
                 android:data="https://osdn.net/projects/gokigen/wiki/PrivacyPolicy" />
         </Preference>
+
+        <PreferenceScreen
+            android:key="debug_info"
+            android:title="@string/pref_degug_info"
+            android:summary="@string/pref_summary_debug_info" />
+
     </PreferenceCategory>
 </PreferenceScreen>