@blog.justoneplanet.info

日々勉強

SimpleCursorTreeAdapterでLoaderManagerを使う

以下のように実装してみた。

public class ExpandableListAdapter extends SimpleCursorTreeAdapter implements LoaderManager.LoaderCallbacks<Cursor> {
    private Context mContext;
    private LoaderManager mManager;
    
    public ExpandableListAdapter(
            Context context, ExpandableListAdapterListener listener, LoaderManager manager, Cursor groupCursor,
            int groupLayout, String[] groupFrom, int[] groupTo,
            int childLayout, String[] childFrom, int[] childTo) {
        super(context, groupCursor, groupLayout, groupFrom, groupTo, childLayout, childFrom, childTo);
        mContext  = context;
        mManager  = manager;
    }
    @Override
    protected Cursor getChildrenCursor(Cursor groupCursor) {
        final long idGroup = groupCursor.getLong(groupCursor.getColumnIndex("_id"));
        Bundle bundle = new Bundle();
        bundle.putLong("idGroup", idGroup);
        int groupPos = groupCursor.getPosition();
        if (mManager.getLoader(groupPos) != null && !mManager.getLoader(groupPos).isReset()) {
            mManager.restartLoader(groupPos, bundle, this);
        }
        else {
            mManager.initLoader(groupPos, bundle, this);
        }
        return null;
    }
    @Override
    public Loader<Cursor> onCreateLoader(int groupPos, Bundle bundle) {
        long idGroup = bundle.getLong("idGroup");
        return new CursorLoader(
                mContext,
                Provider.URI,
                new String[]{Table.ID, Table.ID_GROUP, Table.TITLE, Table.CONTEXT},
                Table.ID_GROUP + " = ?",
                new String[]{String.valueOf(idGroup)},
                Table.CREATED + " DESC"
        );
    }
    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        setChildrenCursor(loader.getId(), cursor);
    }
    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
    }
}

getChildrenCursorでnullを返すとsetChildrenCursorが実行されるまで子要素が消えるのが表示上気になる。あと、getChildrenCursorでnullを返すとAndroid 1.6でクラッシュする。

Androidで圏外になった時に処理をする

■実装

以下の様なBroascastReceiverを用意する。

public class ConnectionReceiver extends BroadcastReceiver {
    private Observer mObserver;
    public ConnectionReceiver(Observer observer) {
        mObserver = observer;
    }
    @Override
    public void onReceive(Context context, Intent intent) {
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = manager.getActiveNetworkInfo();
        if (info == null) {
            mObserver.onDisconnect();
        }
        else {
            mObserver.onConnect();
        }
    }
    interface Observer {
        void onConnect();
        void onDisconnect();
    }
}

MainActivity

以下のようにActivityを実装する。

public class MainActivity extends ActionBarActivity implements ConnectionReceiver.Observer {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.talk);
        IntentFilter filter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
        mConnectionReceiver = new ConnectionReceiver(this);
        registerReceiver(mConnectionReceiver, filter);
    }
    @Override
    protected void onDestroy() {
        unregisterReceiver(mConnectionReceiver);
        super.onDestroy();
    }
    @Override
    public void onConnect() {
        Toast.makeText(getApplicationContext(), "onConnect", Toast.LENGTH_LONG).show();
    }
    @Override
    public void onDisconnect() {
        Toast.makeText(getApplicationContext(), "onDisconnect", Toast.LENGTH_LONG).show();
    }
}

android.permission.ACCESS_NETWORK_STATEがpermissionに必要になる。

ActionbarのHomeButtonを押せるようにする

Actionbar Compatを使った場合にデフォルトではICS以降でHomeButtonがタップできない。android:minSdkVersionは4とする。

public abstract class ActionBarActivity extends FragmentActivity {
    final ActionBarHelper mActionBarHelper = ActionBarHelper.createInstance(this);

    /**
     * Returns the {@link ActionBarHelper} for this activity.
     */
    protected ActionBarHelper getActionBarHelper() {
        return mActionBarHelper;
    }

    /**{@inheritDoc}*/
    @Override
    public MenuInflater getMenuInflater() {
        return mActionBarHelper.getMenuInflater(super.getMenuInflater());
    }

    /**{@inheritDoc}*/
    @SuppressLint("NewApi")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mActionBarHelper.onCreate(savedInstanceState);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            getActionBar().setHomeButtonEnabled(true);
        }
    }
    //以下省略
}

上述のようにすることでタップできるようになる。

参考

Apache SolrをPHPから使う

file_get_contentsとかでlocalhostを叩いても可能ではあるが、Apache Solrを使ってみることにする。

Apache Solr のバージョン 1.3 および 1.4 の両方と互換性があります。

上述のように記載されているが3.6でもとりあえずドキュメントの追加はできる。

■php-pecl-solrのインストール

面倒なのでremiを使う。

yum install --enablerepo=remi,epel php-pecl-solr

mac

peclでインストールする。

pecl install solr

windowsは知らん。

■ドキュメントの追加

以下のようにして、ドキュメントを追加する事ができる。

$client = new SolrClient(array(
    'hostname' => 'localhost',
    'port'     => 8983,
));
var_dump($client);

$doc = new SolrInputDocument();
$doc->addField('id',        '1');
$doc->addField('name',      '梅雨');
$doc->addField('value',     '蒸し暑い,湿気');
$doc->addField('is_public', true);

$updateResponse = $client->addDocument($doc);
$updateResponse = $client->commit();// commitしないとindexが更新されない
var_dump($updateResponse);

■ドキュメントの取り出し

以下のようにしてクエリを発行する事ができる。

$client = new SolrClient(array(
    'hostname' => 'localhost',
    'port'     => 8983,
));
$query = new SolrQuery('*:*');
$query->setStart(0);
$query->setRows(300);
$query_response = $client->query($query);
$response = $query_response->getResponse();
var_dump($response);
/*
object(SolrObject)#4 (2) {
  ["responseHeader"]=>
  object(SolrObject)#5 (3) {
    ["status"]=>
    int(0)
    ["QTime"]=>
    int(0)
    ["params"]=>
    object(SolrObject)#6 (4) {
      ["indent"]=>
      string(2) "on"
      ["wt"]=>
      string(3) "xml"
      ["q"]=>
      string(3) "*:*"
      ["version"]=>
      string(3) "2.2"
    }
  }
  ["response"]=>
  object(SolrObject)#7 (3) {
    ["numFound"]=>
    int(2)
    ["start"]=>
    int(0)
    ["docs"]=>
    array(2) {
      [0]=>
      object(SolrObject)#8 (8) {
        ["created"]=>int(123456789)
        ["face"]=>string(5) "梅雨"
        ["id"]=>string(1) "1"
        ["is_public"]=>bool(true)
        ["tag"]=>string(15) "蒸し暑い,湿気"
      }
      [1]=>
      object(SolrObject)#9 (8) {
        ["created"]=>int(123456789)
        ["face"]=>string(12) "秋雨"
        ["id"]=>string(1) "2"
        ["is_public"]=>bool(true)
        ["tag"]=>string(15) "蒸し暑い,湿気"
      }
    }
  }
}
*/

wt=phpとクエリを投げるとphpの配列で返ってくるのだが以下のメソッドがどうも上手く機能しない。

$client->setResponseWriter("phpnative");
//SolrResponse::getResponse(): Error unserializing raw response.
//Uncaught exception 'SolrException' with message 'Error un-serializing response'

参考

Apache Solrを使ってみる

■インストール

macにインストールする

Javaは既に入ってると思うので、以下のコマンドでダウンロードする。

wget http://ftp.tsukuba.wide.ad.jp/software/apache/lucene/solr/3.6.0/apache-solr-3.6.0.zip
unzip apache-solr-3.6.0.zip
cd apache-solr-3.6.0

CentOSにインストールする

Javaが必要なので以下のコマンドでJavaをインストールする。

yum install java-1.6.0-openjdk
java -version

以下のコマンドでダウンロードする。

wget http://ftp.tsukuba.wide.ad.jp/software/apache/lucene/solr/3.6.0/apache-solr-3.6.0.tgz
tar xvzf apache-solr-3.6.0.tgz
cd apache-solr-3.6.0

■設定

example/conf/schema.xml

<schema>
 <!--typesは大体元のxmlファイルを使う-->
 <fields>
   <field name="id"        type="string"       indexed="true" stored="true"  required="true" /> 
   <field name="name"      type="text_ja"      indexed="true" stored="true"  required="true" />
   <field name="value"     type="text_ja"      indexed="true" stored="true"  required="true" />
   <field name="text"      type="text_ja"      indexed="true" stored="false" multiValued="true"/>
   <field name="is_public" type="boolean"      indexed="true" stored="true"  required="true" />
 </fields>
 <uniqueKey>id</uniqueKey>
 <copyField source="name"  dest="text"/>
 <copyField source="value" dest="text"/>
</schema>

ポート変更

デフォルトは8983で動作するが変更したい場合は以下のコマンドを実行する。

vim etc/jetty.xml

以下の部分を

<Set name="port"><SystemProperty name="jetty.port" default="8983"/></Set>

以下のように変更する。

<Set name="port"><SystemProperty name="jetty.port" default="8080"/></Set>

■データの準備

example/exampledocs/mydata.xml

同じディレクリに入ってるデータを参考に以下のようにしてみる。

<add>
<doc>
  <field name="id">1</field>
  <field name="name">春</field>
  <field name="value">花粉症,花</field>
  <field name="is_public">true</field>
</doc>
<doc>
  <field name="id">2</field>
  <field name="name">夏</field>
  <field name="value">暑い,海</field>
  <field name="is_public">true</field>
</doc>
<doc>
  <field name="id">3</field>
  <field name="name">秋</field>
  <field name="value">紅葉</field>
  <field name="is_public">true</field>
</doc>
<doc>
  <field name="id">4</field>
  <field name="name">冬</field>
  <field name="value">寒い,雪</field>
  <field name="is_public">true</field>
</doc>
</add>

あまり良いサンプルデータとはいえない。

■起動

cd example
java -jar start.jar

■データの登録

以下のコマンドでデータを登録する。

java -jar example/exampledocs/post.jar example/exampledocs/mydata.xml

■遊ぶ

http://localhost:8983/solr/admin/にアクセスする。

■データの削除

solrを止めてから以下のコマンドを実行する。

rm -fr example/solr/data/index

順序を間違えると面倒な事になる。

参考

■nginxをたてる

リモートにsolrを立てる場合は何らかの認証をしたいのでnginxを使ってBasic認証してみる。

wget http://dl.fedoraproject.org/pub/epel/5/x86_64/epel-release-5-4.noarch.rpm
rpm -ivh epel-release-5-4.noarch.rpm
yum install nginx
/sbin/chkconfig nginx on
/sbin/chkconfig --list nginx

nginxの設定

vim /etc/nginx/nginx.conf

以下のように記述する

location / {
    proxy_pass http://127.0.0.1:8389;
    auth_basic "Type your ID and password";
    auth_basic_user_file htpasswd;
}
yum install httpd
htpasswd -c /etc/nginx/htpasswd hoge
/etc/init.d/nginx restart

参考

■起動

再起動時にsolrが起動するようにする。

vim ~/start.sh
#!/bin/bash

cd /home/hoge/apache-solr-3.6.0/example
nohup java -jar /home/hoge/apache-solr-3.6.0/example/start.jar > /home/hoge/log/solr.log &
chmod 0777 start.sh

スクリプトが起動時に実行されるようにする。

sudo crontab -e
@reboot /home/ec2-user/start.sh

参考

proguardを使う

SDKのバージョンは20とする。

■project.propaties

vim project.propaties

以下の行のコメントを外し

# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

以下のようにする。

# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

■proguard-project.txt

vim proguard-project.txt

外部jarを使っている場合、以下のadmobの例のような記述を付加する。

-keep class com.google.ads.** {*;}

WebViewでJavaScriptInterfaceを使っている場合は、対象のメソッドを除外する。

-keep class org.example.JavascriptInterface {
   public *;
}

環境設定 > Android > Build > Build outputをVerboseにする。