From: Tobias Brunner Date: Mon, 2 Jul 2018 16:05:13 +0000 (+0200) Subject: android: Use ListView for log messages X-Git-Tag: 5.7.0dr5~20^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9e05f219fd1057a0c9b2eef58d28d21b31b9cfed;p=thirdparty%2Fstrongswan.git android: Use ListView for log messages This is hopefully a bit more efficient for large log files than the previous single TextView. The ListView widget also provides an auto-scroll mechanism. --- diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LogFragment.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LogFragment.java index 2dda82a57f..625940fd4f 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LogFragment.java +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LogFragment.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2017 Tobias Brunner + * Copyright (C) 2012-2018 Tobias Brunner * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -15,14 +15,17 @@ package org.strongswan.android.ui; +import android.content.Context; import android.os.Bundle; import android.os.FileObserver; import android.os.Handler; +import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; +import android.widget.ArrayAdapter; +import android.widget.ListView; import org.strongswan.android.R; import org.strongswan.android.logic.CharonVpnService; @@ -34,16 +37,15 @@ import java.io.FileReader; import java.io.StringReader; import java.util.ArrayList; -public class LogFragment extends Fragment implements Runnable +public class LogFragment extends Fragment { + private static String SCROLL_POSITION = "SCROLL_POSITION"; private String mLogFilePath; private Handler mLogHandler; - private TextView mLogView; - private LogScrollView mScrollView; - private BufferedReader mReader; - private Thread mThread; - private volatile boolean mRunning; + private ListView mLog; + private LogAdapter mLogAdapter; private FileObserver mDirectoryObserver; + private int mScrollPosition; @Override public void onCreate(Bundle savedInstanceState) @@ -51,7 +53,7 @@ public class LogFragment extends Fragment implements Runnable super.onCreate(savedInstanceState); mLogFilePath = getActivity().getFilesDir() + File.separator + CharonVpnService.LOG_FILE; - /* use a handler to update the log view */ + mLogHandler = new Handler(); mDirectoryObserver = new LogDirectoryObserver(getActivity().getFilesDir().getAbsolutePath()); @@ -61,16 +63,39 @@ public class LogFragment extends Fragment implements Runnable public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.log_fragment, null); - mLogView = (TextView)view.findViewById(R.id.log_view); - mScrollView = (LogScrollView)view.findViewById(R.id.scroll_view); + + mLogAdapter = new LogAdapter(getActivity()); + mLog = view.findViewById(R.id.log); + mLog.setAdapter(mLogAdapter); + + mScrollPosition = -1; + if (savedInstanceState != null) + { + mScrollPosition = savedInstanceState.getInt(SCROLL_POSITION, mScrollPosition); + } return view; } + @Override + public void onSaveInstanceState(Bundle outState) + { + super.onSaveInstanceState(outState); + + if (mLog.getLastVisiblePosition() == (mLogAdapter.getCount() - 1)) + { + outState.putInt(SCROLL_POSITION, -1); + } + else + { + outState.putInt(SCROLL_POSITION, mLog.getFirstVisiblePosition()); + } + } + @Override public void onStart() { super.onStart(); - startLogReader(); + mLogAdapter.restart(); mDirectoryObserver.startWatching(); } @@ -79,118 +104,115 @@ public class LogFragment extends Fragment implements Runnable { super.onStop(); mDirectoryObserver.stopWatching(); - stopLogReader(); + mLogAdapter.stop(); } - /** - * Start reading from the log file - */ - private void startLogReader() + private class LogAdapter extends ArrayAdapter implements Runnable { - try + private BufferedReader mReader; + private Thread mThread; + private volatile boolean mRunning; + + public LogAdapter(@NonNull Context context) { - mReader = new BufferedReader(new FileReader(mLogFilePath)); + super(context, R.layout.log_list_item, R.id.log_line); } - catch (FileNotFoundException e) + + public void restart() { - mReader = new BufferedReader(new StringReader("")); - } + if (mRunning) + { + stop(); + } - mLogView.setText(""); - mRunning = true; - mThread = new Thread(this); - mThread.start(); - } + clear(); - /** - * Stop reading from the log file - */ - private void stopLogReader() - { - try - { - mRunning = false; - mThread.interrupt(); - mThread.join(); + try + { + mReader = new BufferedReader(new FileReader(mLogFilePath)); + } + catch (FileNotFoundException e) + { + mReader = new BufferedReader(new StringReader("")); + } + mRunning = true; + mThread = new Thread(this); + mThread.start(); } - catch (InterruptedException e) + + public void stop() { + try + { + mRunning = false; + mThread.interrupt(); + mThread.join(); + } + catch (InterruptedException e) + { + } } - } - /** - * Write the given log line to the TextView. We strip the prefix off to save - * some space in narrow views (it is not that helpful for regular users anyway). - * - * @param lines log lines to log - */ - public void logLines(final ArrayList lines) - { - mLogHandler.post(new Runnable() { - @Override - public void run() - { - mLogView.beginBatchEdit(); + private void logLines(final ArrayList lines) + { + mLogHandler.post(() -> { + boolean scroll = getCount() == 0; + setNotifyOnChange(false); for (String line : lines) { if (getResources().getConfiguration().screenWidthDp < 600) { /* strip off prefix (month=3, day=2, time=8, thread=2, spaces=3) */ line = line.length() > 18 ? line.substring(18) : line; } - mLogView.append(line + '\n'); + add(line); } - mLogView.endBatchEdit(); - /* calling autoScroll() directly does not work, probably because content - * is not yet updated, so we post this to be done later */ - mScrollView.post(new Runnable() { - @Override - public void run() - { - mScrollView.autoScroll(); - } - }); - } - }); - } - - @Override - public void run() - { - ArrayList lines = null; + notifyDataSetChanged(); + if (scroll) + { /* scroll to the bottom or saved position after adding the first batch */ + mLogHandler.post(() -> mLog.setSelection(mScrollPosition == -1 ? getCount() - 1 : mScrollPosition)); + } + }); + } - while (mRunning) + @Override + public void run() { - try - { /* this works as long as the file is not truncated */ - String line = mReader.readLine(); - if (line == null) - { - if (lines != null) + ArrayList lines = null; + + while (mRunning) + { + try + { /* this works as long as the file is not truncated */ + String line = mReader.readLine(); + if (line == null) { - logLines(lines); - lines = null; + if (lines != null) + { + logLines(lines); + lines = null; + } + /* wait until there is more to log */ + Thread.sleep(1000); } - /* wait until there is more to log */ - Thread.sleep(1000); - } - else - { - if (lines == null) + else { - lines = new ArrayList<>(); + if (lines == null) + { + lines = new ArrayList<>(); + } + lines.add(line); } - lines.add(line); + } + catch (Exception e) + { + break; } } - catch (Exception e) + if (lines != null) { - break; + logLines(lines); } } - if (lines != null) - { - logLines(lines); - } } /** @@ -243,8 +265,7 @@ public class LogFragment extends Fragment implements Runnable @Override public void run() { - stopLogReader(); - startLogReader(); + mLogAdapter.restart(); } }); } diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LogScrollView.java b/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LogScrollView.java deleted file mode 100644 index cf2502271d..0000000000 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/ui/LogScrollView.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2012 Tobias Brunner - * Copyright (C) 2012 Giuliano Grassi - * Copyright (C) 2012 Ralf Sager - * HSR Hochschule fuer Technik Rapperswil - * - * 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. See . - * - * 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 org.strongswan.android.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.widget.ScrollView; - -public class LogScrollView extends ScrollView -{ - private boolean mAutoScroll = true; - - public LogScrollView(Context context) - { - super(context); - } - - public LogScrollView(Context context, AttributeSet attrs) - { - super(context, attrs); - } - - public LogScrollView(Context context, AttributeSet attrs, int defStyle) - { - super(context, attrs, defStyle); - } - - @Override - public boolean onTouchEvent(MotionEvent ev) - { - /* disable auto-scrolling when the user starts scrolling around */ - if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) - { - mAutoScroll = false; - } - return super.onTouchEvent(ev); - } - - /** - * Call this to move newly added content into view by scrolling to the bottom. - * Nothing happens if auto-scrolling is disabled. - */ - public void autoScroll() - { - if (mAutoScroll) - { - fullScroll(View.FOCUS_DOWN); - } - } - - @Override - protected void onScrollChanged(int l, int t, int oldl, int oldt) - { - super.onScrollChanged(l, t, oldl, oldt); - /* if the user scrolls to the bottom we enable auto-scrolling again */ - if (t == getChildAt(getChildCount() - 1).getHeight() - getHeight()) - { - mAutoScroll = true; - } - } -} diff --git a/src/frontends/android/app/src/main/res/layout/log_fragment.xml b/src/frontends/android/app/src/main/res/layout/log_fragment.xml index 6d6abfe164..a51ad4d79a 100644 --- a/src/frontends/android/app/src/main/res/layout/log_fragment.xml +++ b/src/frontends/android/app/src/main/res/layout/log_fragment.xml @@ -1,8 +1,6 @@ +