Android Java から Fluentd にログを送信してみる
環境
- Docker
- fluent/fluentd
- Android Studio
- Java
- Gradle
手順
FluentdのDockerコンテナを準備
$ docker pull fluent/fluentd
fluent.conf を作成
$ mkdir fluent && cd fluent $ mkdir etc log $ cat > "./etc/fluent.conf" <<EOF # Receive events from 24224/tcp # This is used by log forwarding and the fluent-cat command <source> @type forward port 24224 </source> # Match events tagged with "app.*" <match app.*> @type file path /fluentd/log/app.*.log symlink_path /fluentd/log/app.log append true time_slice_format %Y%m%d time_slice_wait 1m time_format %Y%m%dT%H%M%S%z </match> EOF
configは docs.fluentd.org をベースに雑に書きました。
$ docker run -it --rm \ --name docker-fluent-logger \ -p 24224:24224 -p 24224:24224/udp \ -v $(pwd)/log:/fluentd/log \ -v $(pwd)/etc:/fluentd/etc \ -e FLUENTD_CONF=fluent.conf \ fluent/fluentd:latest
Android側
$ grep fluent app/build.gradle // https://mvnrepository.com/artifact/org.fluentd/fluent-logger api group: 'org.fluentd', name: 'fluent-logger', version: '0.3.2'
$ grep uses-permission app/src/main/AndroidManifest.xml <uses-permission android:name="android.permission.INTERNET"/>
package com.example.fluentloggertest; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuItem; import android.view.View; import org.fluentd.logger.FluentLogger; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { new Thread() { @Override public void run() { FluentLogger LOG = FluentLogger.getLogger("app", "fluentdのDockerコンテナが動いているマシンIP", 24224); LOG.log("action", "MainActivity", "onClickFab"); // こんな感じ? } }.start(); } }); } ...
プロジェクトテンプレから、デフォルトでFabがあるものを使っています。
logを確認
↑のアプリでFabをクリックすると、、
$ tail -f ./log/app/* ==> ./log/app.foo-bar.log <== 2018-09-20T01:34:26+00:00 app.action {"MainActivity":"onClickFab"} 2018-09-20T01:34:28+00:00 app.action {"MainActivity":"onClickFab"}
こんな感じでログが保存されます! (あー、この app.log のシンボリックリンクはコンテナ内のpathですね…)
超雑ですが、以上です。m(_ _)m
Androidデバイスでディスプレイ解像度変更
前回↓のような記事を書いた通り(?)、私はディスプレイを広く使いたくてしょうがない人間です。 sashimi4.hatenablog.com
そしてAndroidデバイスに於いても解像度を変更する手段を発見したので記します。
Android開発環境(adb環境)をセットアップ
省きます。 For geek
とつけたのはそういう意味です。
なお、 adbさえあればいいミニマルな環境構築方法は他の方もよく紹介されていますので、ググっていただければ簡単に見つかるかと思います。
adbコマンド実行
規定(≒現在)の解像度を確認。
$ adb shell wm size Physical size: 720x1280
好みの解像度を設定。 & 任意解像度でオーバーライド出来ているか確認。
$ adb shell wm size 1080x1920 ~ $ adb shell wm size Physical size: 720x1280 Override size: 1080x1920
この端末は4Kは無理でした 😇
$ adb shell wm size 2160x3840 ~ $ adb shell wm size Physical size: 720x1280 Override size: 1440x2560
こんな感じで弄れます。
使ってみたメモ
- 本変更は端末を再起動しても持続されるようです。
- IME設定でキーの高さを最大にすると操作性が上がります。
- 画面の隅の方をタッチすると、タッチ補正により意図しない座標がタッチされることがありました。おそらくdpiの変更により補正条件に悪影響が出ているのでしょうかね…
とりあえず以上です。
コマンドラインからMacOSの画面解像度を変更する
DisplayMenuとかQuickResといったGUIアプリも有るし持っているんだけど、コマンドラインからいじりたくなったのでメモ。
Installation
$ brew install homebrew/cask/cscreen ==> brew cask install homebrew/cask/cscreen ==> Satisfying dependencies ==> Downloading http://www.pyehouse.com/wp-content/uploads/2012/09/cscreenIntel.dmg ######################################################################## 100.0% ==> Verifying checksum for Cask cscreen ==> Installing Cask cscreen ==> Linking Binary 'cscreen' to '/usr/local/bin/cscreen'. 🍺 cscreen was successfully installed!
Usage
Show display list
$ cscreen -l DisplayID Index Depth Width Height Refresh 4280a40 1 32 2560 1600 0 use -h to display all usage options
Show available settings for display
$ cscreen -s1 -v DisplayID Index Depth Width Height Refresh 4280a40 1 32 2560 1600 0 4280a40 2 32 1280 800 0 4280a40 3 32 2048 1280 0 4280a40 4 32 1650 1050 0 4280a40 5 32 1440 900 0 4280a40 6 32 1152 720 0 4280a40 7 32 840 524 0 4280a40 8 32 1024 768 0 4280a40 9 32 800 600 0 4280a40 10 32 640 480 0 use -h to display all usage options
※ ディスプレイが1つしか無いので -s1
は省略可。
MacBook Pro内蔵のRetinaディスプレイなんですが、リフレッシュレートが見えませんね... :thinking_face:
Set display as you like!
$ cscreen -s1 -x 2560 -y 1600
私はメインでMacBook Pro (Retina, 13-inch, Early 2015)を使っているので、上記のコマンドでDotByDot表示できます。
その他は -d
オプションでDepthや -r
オプションでRefresh rateを設定できるようです。
詳しくは -h
オプションでヘルプを見ると良いと思います。
比率が合うわけない 1920x1080 とか、その他中途半端な値等を指定すると、 cscreen -s1 -v
で表示された中の近似値が選ばれるみたい?
ちなみにドット数を超えた解像度は設定できない模様。他のGUIアプリだと設定できるんですけどね…。
以上です。
さくらのクラウドでVPN(L2TP/IPsec PSK)サーバを簡易構築
利用ツール/技術
手順
# 注意 - 本手順を適用すると、サービス利用料が発生します。 - 一身上の都合により英語版コントロールパネルを利用しています。 - 本スクリプトの利用により損害が発生しても、私は一切の責任を負いかねます。
※ 会員登録方法等については省略します。詳しくは下記リンク先をご覧ください。 cloud.sakura.ad.jp
今回は、設定を自動化するためのスクリプトを用意しました。
このスクリプトを さくらのクラウド の "スタートアップスクリプト" 機能に通すことで設定を自動化することができます。
スタートアップスクリプト機能とは、サーバ起動時に任意スクリプトを実行し、 パッケージのインストールや各種設定作業の自動化などを簡単に実現できる機能です。 本手順では、さくらのクラウド側で用意されているものではなく、VPNサーバのセットアップ用のカスタムスクリプトを登録して使います。
さくらのクラウドは時間課金ですので、 設定を自動化 して、 使いたいときに立て て 使わないときは削除 すればコスト面もうれしいですねっ。
スタートアップスクリプトを登録
IaaSを選択します。
設定 > Script
の順に開きます。
↓のスクリプトを↑の画像のようにコピペします。
以上でスクリプトの登録は完了です。
サーバを作成(スタートアップスクリプト実行)
サーバを作成します。
デフォルトでSimple modeにチェックが入っていますが、 必ず外します 。
スペックは好みに設定して大丈夫です。
Disk source
に Archive
を選択し、 Ubuntu 16.04
を選択します。
次に、 Modify disk
にて、先程追加したスクリプトを選択します。
すると、VPN接続の認証情報の入力フォームが表示されるので、任意のものを入力します。
後は作成ボタンを押すだけで、スクリプトが自動で設定を行います。
動作確認
サーバ一覧を開き、サーバが起動していることを確認します。 (起動していなかったら起動します。)
今回はMacで動作確認をします。
ネットワーク設定からVPN設定を追加します。
次にサーバのIPアドレスと、サーバ作成時に設定したユーザ名を入力します。
続いて認証設定を開き、 同じく、サーバ作成時に設定したパスワードと事前共有鍵(PSK)を入力・設定します。
後は接続ボタンを押せば繋がるはずです。
送受信できていることがわかります。
なお、好み・環境によっては、 Advanced から、すべてのトラフィックをVPNを通すように設定しても良いでしょう。
これでCMANさんなんかで確認すると、ゲートウェイIPがさくらのクラウドのIPアドレスになっていることがわかります。
手順は以上です。
Have a nice VPN life!
Ubuntuのiptablesを永続化する
configファイルを作成
デフォルト設定に加えたいものがある場合
e.g.
$ sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE # 任意の設定の例 $ sudo sh -c "iptables-save > /etc/iptables.rules"
希望の設定がある場合
e.g.
$ sudo bash -c "cat >/etc/iptables.rules" <<EOF # 以下、任意の設定の例 *filter :INPUT ACCEPT [2426:480164] :FORWARD ACCEPT [1902:649674] :OUTPUT ACCEPT [2166:1094891] :f2b-sshd - [0:0] -A INPUT -p tcp -m multiport --dports 22 -j f2b-sshd -A INPUT -p tcp -m multiport --dports 22 -j f2b-sshd -A f2b-sshd -j RETURN -A f2b-sshd -j RETURN COMMIT # Completed on Thu Apr 19 16:00:35 2018 # Generated by iptables-save v1.6.0 on Thu Apr 19 16:00:35 2018 *nat :PREROUTING ACCEPT [810:66915] :INPUT ACCEPT [58:8731] :OUTPUT ACCEPT [19:1213] :POSTROUTING ACCEPT [0:0] -A POSTROUTING -o eth0 -j MASQUERADE COMMIT EOF
起動時の読み込み設定
$ sudo sed -ie "/^iface eth0.*$/a \ pre-up iptables-restore < /etc/iptables.rules" /etc/network/interfaces
これで eth0がupするときに設定が読み込まれます。 if名は適宜変更してください。
"No Internet Connection Dialog" in Android
「インターネットに接続できません。設定を確認してください。」っていうあのダイアログをサクッと実装します。
地味なのでqiitaではなくここに書きます 😇
大まかな実装
- パーミッション :
ACCESS_NETWORK_STATE
を追加。
app/src/main/AndroidManifest.xml
... <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> ...
- ステータスチェックをするメソッドを追加
任意の場所(*)に追加します。
... public boolean isOnline() { ConnectivityManager connectivityManager = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo netInfo = null; if (connectivityManager != null) { netInfo = connectivityManager.getActiveNetworkInfo(); } return netInfo != null && netInfo.isConnected() && netInfo.isAvailable(); } ...
- 接続状況を判定&ダイアログで設定画面を案内
任意の場所(*)で先程のメソッドで判定し、オンラインでなければダイアログで設定画面を案内します。
if (!isOnline()) { new AlertDialog.Builder(this) .setTitle("No internet connection") .setMessage("A network connection is required.") .setIcon(android.R.drawable.ic_dialog_alert) .setPositiveButton("Open wireless settings", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS)); } }) .show(); return; }
動作
※ サンプルはMainActivityで判定するようにしました
機内モードで起動すると、ダイアログが表示されます。
positiveButton押下で、設定画面のWi-Fi設定画面へ移動します。
想定した動作はバッチリです。
任意の場所(*) について補足
主に以下のいずれかで行うことになるかと思います。
- アプリ起動時に最初に呼ばれるActivity
- MainActivity
- スプラッシュスクリーンのActivity
- 基底Activity方式ならBaseActivity
- Applicationクラス
ActivityLifecycleCallbacks
を実装して、onActivityResumed(...)
辺りで判定すると、漏れがない感じでしょうか。
以上です。
イースターエッグ等でのAndroidのボタン連打検知について
ふと、いま作っているアプリにイースターエッグを入れようと思い、ボタン連打の検知について簡単に考えてみました。
一番単純な、ボタンを一定回数/速度で連打すると何かが出てくるタイプです。
雑にやってみた
public class MainActivity extends AppCompatActivity { public static long CLICK_LIMIT_INTERVAL = 3000; private int count = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View view) { count++; if (count >= 10) { Snackbar.make(view, "Wow!!!", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); count = 0; return; } new Handler().postDelayed(new Runnable() { public void run() { if (count > 0) { count--; } } }, CLICK_LIMIT_INTERVAL); } }); } ...
雑〜にこんな感じで書いてみました。(プロトタイピングなのでfabかつMainActivityでやっています。) 3秒間で10回タップしないといけないようになっています。
ゆっくり押していると、10カウント到達前に最初に押したボタンからカウントが無効化(--;)されていく仕組みです。 単純で微妙に穴がありそうですが、とりあえずこれでもいいかなと思います。
おまけ : 本家はどうなっているか覗いてみた
本家イースターエッグ
最小3回のタップで行けるようです。
軽くトレースした感じ、最初のタップから3回目まで500msという制限になっているようです。たぶん。
System.arraycopy(...)
とか久しぶりに見た…。
開発者向けオプションを表示するアレ
Android4.2以降は開発者向けオプションが隠れていて、ビルド番号を連打しないと表示されないのは皆さんご存知かと思います。
こちらは、インターバル関係なしに7回タップすれば良いようですね。
もう一度やりたくなったら
もう一度開発者向けオプションを非表示にしたい場合は、 設定アプリ
の詳細から データを消去
を行うことで可能のようです。
以上、メモ書きでした。