CentOS7にアップグレードしたらApacheのバージョンが2.4になった!

CentOS6の頃はApacheのバージョンは2.2がプリインストールされていたのだが、
CentOS7にアップグレードしたら、バージョン2.4になってしまった。

そのままで「service httpd start」と打ち込んでも起動しない。

ちなみに、CentOS7からは「service」コマンドは「systemctl」に変わったらしい。
今までどおり、「service」コマンドを実行すると、「systemctl」コマンドにプロキシしてくれるみたい。

ここではApache2.2からApache2.4にアップグレードした場合のマイグレーションについて記述しておきたい。

httpd: Syntax error on line 154 of /etc/httpd/conf/httpd.conf: Cannot ...ctory

肝心なところが切れているが、ディレクトリがないということなのだろう。
httpd.confの154行目の記述は以下。

LoadModule authn_alias_module modules/mod_authn_alias.so

よくわからないが、コメントアウトして消しておこう。

httpd: Syntax error on line 157 of /etc/httpd/conf/httpd.conf: Cannot load modules/mod_au...rectory

httpd.confの157行目は以下。

LoadModule authn_default_module modules/mod_authn_default.so

同様にコメントアウト

httpd: Syntax error on line 163 of /etc/httpd/conf/httpd.conf: Cannot load modules/mod_au...rectory

httpd.confの163行目は以下。

LoadModule authz_default_module modules/mod_authz_default.so

上に同じくコメントアウト

httpd: Syntax error on line 164 of /etc/httpd/conf/httpd.conf: Cannot load modules/mod_ld...rectory

httpd.confの164行目は以下。

LoadModule ldap_module modules/mod_ldap.so

コメントアウト

httpd: Syntax error on line 165 of /etc/httpd/conf/httpd.conf: Cannot load modules/mod_au...rectory

httpd.confの165行目は以下。

LoadModule authnz_ldap_module modules/mod_authnz_ldap.so

はい!コメントアウト

httpd: Syntax error on line 200 of /etc/httpd/conf/httpd.conf: Cannot load modules/mod_di...rectory

httpd.confの200行目は以下。

LoadModule disk_cache_module modules/mod_disk_cache.so

同じくコメントアウト

これで動くようになった。
全部コメントアウトしてよかったんだろうか・・・・とは思うけど。

Androidでドラッグアンドドロップを実装する

タイトルまんまです。Androidドラッグアンドドロップの実装をやってみます。
イメージはこんな感じ。

f:id:ats337:20161101220040p:plain:h240:left
画面は左右にペインを設け、左に「Move Me!」というテキストを配置します。









f:id:ats337:20161101220045p:plain:h240:left
「Move Me!」を長押しすると、ドラッグが開始します。
そのままドラッグし、右ペインにドロップします。








f:id:ats337:20161101220048p:plain:h240:left
ドロップしたら右ペインに「Move Me!」が移動します。











以下にソースコードを示します。

  • drag_and_drop.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:id="@+id/left_layout" ---①
        android:orientation="vertical">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="22sp"
            android:background="#00ffffff"
            android:text="Move Me!"
            android:id="@+id/move_text"/> ---②

    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="vertical"
        android:id="@+id/right_layout" ---③
        android:background="@color/wallet_bright_foreground_holo_dark">

    </LinearLayout>
</LinearLayout>

①LinearLayoutで左ペインを構成
 idはleft_layout
②「Move Me!」をTextViewで構成
 idはmove_text
③LinearLayoutで右ペインを構成
 idはright_layout

  • DragAndDropActivity.java
public class DragAndDropActivity extends Activity {

    private TextView tvMove;
    private LinearLayout leftLayout;
    private LinearLayout rightLayout;
    private MyDragListener listener;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.drag_and_drop);
        tvMove = (TextView) findViewById(R.id.move_text);
        leftLayout = (LinearLayout) findViewById(R.id.left_layout);
        rightLayout = (LinearLayout) findViewById(R.id.right_layout);
        tvMove.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                ClipData data = ClipData.newPlainText("text", ((TextView)view).getText().toString());
                view.startDrag(data, new View.DragShadowBuilder(view), (Object)view, 0); // ---①
                return true;
            }
        });

        listener = new MyDragListener();
        leftLayout.setOnDragListener(listener);   ---②
        rightLayout.setOnDragListener(listener); ---②
    }


    private class MyDragListener implements View.OnDragListener {
        @Override
        public boolean onDrag(View view, DragEvent dragEvent) {  ---③
            switch (dragEvent.getAction()) {
                case DragEvent.ACTION_DRAG_STARTED: {
                    // ドラッグ開始時
                    View dragView = (View) dragEvent.getLocalState();
                    dragView.setBackgroundColor(Color.LTGRAY);
                    ((TextView)dragView).setTextColor(Color.WHITE);
                    return true;
                }
                case DragEvent.ACTION_DRAG_ENTERED: {
                    break;
                }
                case DragEvent.ACTION_DRAG_LOCATION: {
                    break;
                }
                case DragEvent.ACTION_DRAG_EXITED: {
                    break;
                }
                case DragEvent.ACTION_DROP: {
                    View dragView = (View) dragEvent.getLocalState();
                    dragView.setBackgroundColor(Color.TRANSPARENT);
                    ((TextView)dragView).setTextColor(Color.BLACK);

                    ((LinearLayout) dragView.getParent()).removeView(dragView);
                    ((LinearLayout) view).addView(dragView);
                    break;
                }
                case DragEvent.ACTION_DRAG_ENDED: {
                    // ドラッグ終了時
                    Log.v(getClass().getSimpleName(), "ACTION_DRAG_ENDED");

                    return true;
                }
            }
            return true;
        }
    }
}

①ドラッグを開始する
 「Move Me!」を長押しすることでドラッグを開始します。
 ドラッグを開始するメソッドはview#startDrag()です。
②ドラッグを受け付ける
 ドラッグを受け付けるためにはView#setOnDragListener()メソッドを呼び出し、
 OnDragListenerを実装したクラスを設定する必要があります。
 ドラッグ処理の振る舞いはOnDragListenerクラスの実装で行います。
③ドラッグ操作のリスナを実装する
 OnDragListenerを実装したMyDragListenerクラスを作ってみました。
 onDragメソッドを実装する必要があります。
 onDragメソッドには
 第1引数としてドラッグリスナを設定したView
 第2引数としてDragEventクラスのインスタンスを受け付けます。
 DragEvent#getActionメソッドでどんなイベントが発生したか判定しながら処理を実装していくことになります。

CentOS7にアップデートしてからネット接続できない(NetworkManagerが起動していない)

先日記事にしたとおり、CentOS7にアップデートしてから何かとおかしい。

CentOS7にアップデートしてからライブラリが見当たらない【No such No such file or directory】 - My Happiness

今度はネットワークがおかしい・・・・。

# nmcli d show

Error: NetworkManager is not running.

NetworkManagerを起動することで解決

# service NetoworkManager start

ついでに・・・・

# chkconfig NetworkManager on

以下を参考にしました。
Chapter 10. NetworkManager

CentOS7にアップデートしてからライブラリが見当たらない【No such No such file or directory】

CentOS6からCentOS7にアップデート後にいろいろ問題が起きたので備忘のために残しておきます。

grepコマンドとか使えなくって以下のようにエラーが発生してしまっていた。

grep: error while loading shared libraries: libpcre.so.0: cannot open shared object file: No such file or directory

libpcre.so.0へのアクセスができないようなので、libpcreのインストールを行った。

# yum install pcre-devel

f:id:ats337:20160613002430p:plain
するとこんなエラーが・・・・・

シンボリックリンクを貼ることで解決できた。

ln -s /lib64/libsasl2.so.3 /lib64/libsasl2.so.2
ln -s /lib64/libpcre.so /lib64/libpcre.so.0

以下のサイトを参考にさせていただきました。
CentOS7へのアップデートでハマった - Qiita
CentOS 6.5からCentOS 7.0へのアップグレード(補足トラブル:対処) - Marlock Homes Diary

Google Sign-In for Androidを試してみる

Android向けのGoogle Sign-In for Androidを試してみた。

Android端末に登録しているGoogleアカウントで、
Googleに自動ログインを行えるというもの。

以下をやってみただけなので、英語がわかれば以下のサイトを見るのが早いかも。
Try Sign-In for Android  |  Google Sign-In for Android  |  Google Developers

動作環境

Mac Book Pro (Mac OSX 10.11)
Android Developer 2.1

①サンプルプロジェクトを取得する

ターミナルを開いてgitでプロジェクトを取得する。

$ git clone https://github.com/googlesamples/google-services.git

Android Studioを開いて、取得したプロジェクトを開く。
上記のgoogle-services.gitは、Google Servicesの全てのサンプルが含まれているため、
google-services/android/signinを開くこと

②設定ファイルを取得する

取得したサンプルプログラムはそのままでは使用できないそう。
google-services.jsonが必要らしい。

上記リンクより、google-services.jsonを生成するようだ。
Add Google Services  |  Google Developers

順番に説明する。

f:id:ats337:20160510213235p:plain
App nameとAndroid package nameを入力して、
OCNTINUE TO Choose and configure servicesボタンを押す。

App nameとAndroid package nameはとりあえずデフォルトで作成する。

f:id:ats337:20160510213946p:plain
Google Sign-Inを選択する。
すると、下部に証明書のフィンガープリントを入力する項目が現れる。
keytoolを使用して証明書を作成する。
ターミナルを開いて以下のコマンドを実行する。

keytool -exportcert -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore

(パスワードはandroid)

上記はデバッグ用のkeystoreファイルからフィンガープリントを取得したが、
実際にアプリに組み込む際には、署名を行うkeystoreから取得する。

上記のコマンドで取得したSHA1のフィンガープリントを画面に入力すると、
ENABLE GOOGLE SIN-INボタンが押せるようになるので押す。
更にその下の
CONTINUE TO Generate configuration filesボタンを押す。

f:id:ats337:20160510215543p:plain

Download google-serivice.jsonボタンを押して、
ファイルをダウンロードする。

③設定ファイルをプロジェクトフォルダに配置する

ダウンロードしたファイルは、google-services/android/signin/app直下にコピーしておく。

④サーバのWeb Client IDを作成する

サンプルのIdTokenActivityとServerAuthCodeActivityはOAuth 2.0 Web Client IDが必要。
Client IDを作成するには以下のようにする。

Credentialページにアクセスする
Google API Console

f:id:ats337:20160512001548p:plain
作成したプロジェクトを選択して続行ボタンを押す。

f:id:ats337:20160512001758p:plain
Android client for....のところのクライアントIDをコピーする。

サンプルプロジェクトのstring.xmlファイルの

<string name="server_client_id">YOUR_SERVER_CLIENT_ID</string>

の部分にコピーしたクライアントIDを設定する。

これで準備完了。
あとはアプリを起動して動作確認!

Android API23でIPv4アドレスの判定

IPアドレスIPv4かどうかの判定を行うために、
以下のように、 InetAddressUtils.isIPv4Address(ipAddress)で判定するようなコードを書いていた。

Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
for (e.hasMoreElements()) {
    NetworkInterface networkInterface = e.nextElement();
    Enumeration<InetAddress> e2 = networkInterface.getInetAddresses(); 
    for (e2.hasMoreElements();) {
        InetAddress inetAddress = e2.nextElement();
        String ipAddress = inetAddress.getHostAddress();
        if (InetAddressUtils.isIPv4Address(ipAddress)) {
            // 〜IPv4アドレスの場合の処理〜
        }
    }
}

ただし、これはAndroid API23(Android 6.0)以前の話。
Android API23はApacheのHttpClientがなくなっているため、
上記APIは利用できない。

API23以降はInetAddressクラスがInet4Addressクラスのインスタンスかどうか
で判定することにする。

inetAddress instanceof Inet4Address

2016年5月4日 家族でグリーンランド 〜フリーパス?回数券?〜

熊本は荒尾グリーンランドに家族で行ってきました。
半月前に大きな地震が起きたばかりですが、余震もなく安全そのものでしたが、
敬遠した人もいたのかもしれません。
しかしながら、さすがGW中日!かなりの人でした!

いつもと同じようにフリーパスで入りましたが、
前にもやったように入場券+回数券で入った時に比べてどれだけ得したかを記しておきます。
myhappiness.hatenablog.com


我が家は、大人2人、こども1人、リトル(※)1人という構成です。
※リトル:身長120cm以下のこども

入場料+フリーパスの場合

フリーパスの場合は、入場料込みで18,500円になります。

入場料+回数券の場合

アトラクション のべ回数 1回に必要な枚数 使用した枚数
スカイシップ 4 3 12
ゴーカート 13 2 26
スピンマウス 4 4 16
ぐるり森大冒険 4 5 20
スカイリフト 8 2 16
魔女のフライングトリック 6 4 24
スフィンクスコースター 4 3 12
グランパスジェット 8 5 40
ティーカップ 3 2 6
急流すべり 4 5 20
スプラッシュ 4 4 16
ブラックホールコースター 8 6 48
リフト 4 2 8
カイジェット 6 3 18
メリーゴーランド 2 3 6
ガオー 2 8 16
ウェーブスインガー 2 2 4
ドラゴンリバー 4 7 28

回数券にして336枚分のアトラクションに乗ったことになります。

回数券は1枚110円、30枚綴りで3,000円です。
1枚100円と考えて計算すると、本日利用したアトラクションは
33,600円(336枚 × 100円/枚)
になります。

入場料は4,800円です。
合計で38,400円になります。

結局どっちがお得?

フリーパスで入った方19,900円お得という結果になりました。

その他諸々

GWということで、7:30〜20:30まで開園してました。
終わりの時間は調べていたのですが、7:30スタートとは知らず、9:00頃入場しました。
20:30目一杯まで楽しみ、20:00から5分ほど花火が上がりました。

人はかなり多く、14:00頃がピークだったように感じました。
ガオーに60分、スプラッシュとブラックホールコースターに40分、
グランパスジェットに30分待ちました。
今日は効率重視で乗りまくったわけではなく、
園内を歩き回ったり休んだり食べたり、途中で一度退場してドラッグストアに行ったりしました。

今日は天気がよく、日差しが強かったので、日焼けしまくり。
1日中外にいて、かなり疲労もあるけれど、普段会えない家族たちに、よいサービスできました。