Notification表示するならNotification.builderのが楽っぽい

androidのNotificationで引っ張った時に見えるやつをカスタマイズする方法

xmlを作る

カスタマイズしたいレイアウトのxmlを作成する

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#00ffffff"
    android:padding="5dp" >

    <ImageView
        android:id="@+id/imgIcon"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_marginRight="10dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    
        <TextView
            android:id="@+id/txtTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textStyle="bold"
            android:layout_marginBottom="5dp"
            style="@android:style/TextAppearance.Medium" />
    
        <ProgressBar
            android:id="@+id/pgsDownload"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </LinearLayout>

</LinearLayout>

設定

これをNotificationに設定すればうまく動く

	Notification notification = new Notification();
	notification.contentView = new RemoteViews(getPackageName(), R.layout.notice_download_progress);

	NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
	notificationManager.notify(NOTIFICATION_ID, Notification);

注意

これ以下の条件で、背景色が勝手に設定されるらしい

  • setContentでRemoteViewsをセット
  • PackageのtargetSdkVersionが”9″未満の場合

詳しくはこちらを。

http://d.hatena.ne.jp/baroqueworksdev/20120213/1329152000

まとめ

と、ここまで作っておきながらもNotificationに関してはNotification.builderを使ったほうが簡単で綺麗にできそう。Notificationってアプリ内に完結していないんで端末として統一されたものが表示されないと汚く見えてしまう。なので、カスタマイズせずにNotification.builder使って作ったほうが良さげ。

Notification.builderの使い方

ここまで書いたし、Notification.builderを使う場合のやりかた。

	Notification.Builder builder = new Notification.Builder(getApplicationContext());
	builder.setTicker("ticker");
	builder.setContentTitle("title");
	builder.setContentText("text");
	builder.setSmallIcon(android.R.drawable.ic_dialog_info);
	Notification notification = builder.getNotification();

	NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
	manager.notify(0, notification);

随分簡単。綺麗だしいいと思う。ただ、API Level 11以上必要ってのはハードルが高いよなぁ。API Level 11未満の場合は以下のリンクを参考にやりましょ。

http://blog.haw.co.jp/android/?p=332

ListViewでPull to refreshを実現する方法

色々なLibraryがあるけど、android-pulltorefreshが一番良さげ

使い方

まずは、下からソースをダウンロードする。

android-pulltorefresh

EclipseにImport

普通にImport。[ File → Import → Android ]で、ダウンロードしたフォルダを選択してImportする。

Libraryに設定

作成中のProjctを右クリックして[ Properties → Android ] から Library で Add でさっきImportしたやつを選択する

コード

Pull to Refreshに変更したいListViewをcom.markupartist.android.widget.PullToRefreshListViewに変更

    <com.markupartist.android.widget.PullToRefreshListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

んで、普通に取ってきて設定

	listView = (PullToRefreshListView) findViewById(R.id.listView);
	listView.setAdapter(adapter);
	listView.setOnRefreshListener(new OnRefreshListener() {
		@Override
		public void onRefresh() {
			// pull to refresh時に呼ばれる

			// なんかしらの動作

			// こいつが呼ばれることでアニメーションが終わる
			listView.onRefreshComplete();
		}
	});

他に試したもの

RefreshableListView

ListViewをPull to Refreshできるように拡張しただけのシンプルなもの。以下からダウンロード

RefreshableListView

んで、プロジェクトに設定して動かそうとしたけど何をやっても動かない。どう設定すればうごくのかいまだに分からず。

Android-PullToRefresh

ListViewだけではなくて色々なものが含まれている多機能pull to refreshのやつ。以下からダウンロード

Android-PullToRefresh

こいつを最初使おうとしたんだけど、ListViewでなぜかsetOnItemLongClickListenerが設定できない。。。今回はLongClickを元に動かさないといけなかったから断念した。WebViewとかでpull to refreshをしたい場合はこいつ使えばいいんじゃないかなー。



SQLiteDatabase.query()で色々な値を取得する方法

AndroidのSQLiteDatabaseでquery()を使ってデータを取得する場合の覚書。

パラメータ

ここに詳しく書いてある

Android データベースのデータを読み込む(Select)

Cursor query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) 
  • 引数distinctには、trueを指定すると検索結果から重複する行を削除します。
  • 引数tableには、テーブル名を指定します。
  • 引数columnsには、検索結果に含める列名を指定します。nullを指定すると全列の値が含まれます。
  • 引数selectionには、検索条件を指定します。
  • 引数selectionArgsには、検索条件のパラメータ(?で指定)に置き換わる値を指定します。
  • 引数groupByには、groupBy句を指定します。
  • 引数havingには、having句を指定します。
  • 引数orderByには、orderBy句を指定します。
  • 引数limitには、検索結果の上限レコードを数を指定します。

where句

whereはSelectionとSelectionArgsを設定しましょう。値を設定する場所を「?」に、設定する値をSelectionArgsに入れます。

	String selectStr = "id=?";
	String[] selectArg = { "0" };
	Cursor c = db.query(TABLE_NAME, null, selectStr, selectArg, null, null, null);

sort

sortはorderByに指定しましょう。複数指定することも可能だそうです。

	String orderStr = "price desc, create_date desc";
	Cursor c = db.query(TABLE_NAME, null, null, null, null, null, orderStr);

limit, offsetの指定

limitに値を設定しましょう。limitの値を設定すると言いながらoffsetもここに設定します。書き方はoffset, limitの順番です。

	String limitStr = String.valueOf(offset) + "," + String.valueOf(limit);
	Cursor c = db.query(ENTRY_TABLE_NAME, null, null, null, null, null, null, limitStr);

まとめ

簡単なのはQuery使ってやればいいけど、複雑なことはexecSQL()でやったほうが捗ると思う。

はてブをシンプルに表示するSimpleHatebuを作った

はてブのタイル表示が非常に評判が悪くてシンプルにはてブを表示するページを作るのが流行ってるっぽい。ちょっと時期が過ぎたような気がしなくもないけど、便乗してSimpleHatebuってのを作ってみた

SimpleHatebu

どんなもの?

Yahooのニュースサイトのデザインを参考にカテゴリ別に表示する新着ページ。カテゴリを選択すればそのジャンルの新着が表示される。下の数ははてブ数の閾値を選択できる。至って単純。

開発の話

このページはすべてjavascriptで動いてる。どうやって値をとっているかというと、Google Feed APIを使ってる

Google Feed API  |  Google Developers

はてブってエントリーページにmode=rssのクエリパラメータを渡してあげるとrssで取得できるようにできてるから、そのRSSをGoogle Feed APIで取得してきてボタンが押されるたびに表示を入れ替えているっていう仕組み。Google Feed APIの使い方はすごい簡単。Google Feed APIの大本をもってきて、

        <script type="text/javascript" src="https://www.google.com/jsapi"></script>

こんなかんじで取れる

	google.load("feeds", "1");
	google.setOnLoadCallback(initialize);

	var initialize = function() {
		// URL指定してFeed作る
		var feed = new google.feeds.Feed('取得したいFeedのURL');
		// 取得するFormatを指定。JSONでも取れる
		feed.setResultFormat(google.feeds.Feed.XML_FORMAT);
		// 取得する件数を指定
		feed.setNumEntries(10);
		// 実際に取得
		feed.load(function(result) {
			// とれた値で好きに動かしましょー
		});
	};

で、再読み込みした時にカテゴリとかはてブの閾値とかが元に戻るのが気に食わなかったんでjQueryCookieを使って選択してるカテゴリとかをCookieにセットしてみた。こいつも使い方はすごい簡単。まず大本を持ってきて、

        <script type="text/javascript" src="./js/jquery.cookie.js"></script>

こんな感じで値の保存と取得ができる

	// 保存
	$.cookie('key', 'value');
	// 取得
	key = $.cookie('key');

本当はすべてのエントリーに対してはてブ数の閾値を設定できるようにしたかったんだけど、なぜかthresholdのクエリパラメータを設定してカテゴリのエントリーを取得すると最新のものではなく8月31日のデータがとれてしまう。はてな側が返答してる値が最新じゃないからこっちじゃどうしようもなくて本気だすとHTMLをGETしてパースして表示みたいなことをやるしかないみたいで、それをやるにはサーバ側のコードがどうしても必要だからしょうがなくカテゴリ別のものは新着だけしか取れないようにしてる。

まとめ

もともとはタイルでも見やすく作れるんじゃね?ってことでタイルっぽく作ろうとしてたんだけど、全然見やすくならなかった。タイルのいいところって情報をカテゴライズしたい場合にしか有効じゃないんだと思う。はてブみたいに文字データが基本でタイルでやろうとするとどうしても目の動きがきつくなるから、シンプルに文字だけで表示してカテゴリーごとにタイルにするっていうYahooニュースみたいな作りじゃないと見づらいと思う。それにしてもGoogle Feed APIはすごい便利。これ使えば簡単にiGoogleも再現できるんじゃないかなー。今度時間があったら作ってみようかな。

DropboxAPIを使ってファイル一覧を表示

DropboxAPIの使い方を知るためにファイル一覧を表示できるものを作ってみた

ダウンロード

以下のURLからSDKはダウンロードできる。

Python Core SDK Installation – Dropbox

API keyの発行

以下のURLにアクセスしてAPI keyをとる

Dropbox – Sign in

Android Manifestを修正

InternetにアクセスするPermissionが必要だから追加

    <uses-permission android:name="android.permission.INTERNET"></uses-permission>

ついで、認証用のdropboxのActivityを設定。db-hogehogeのhogehoge部分をAPI Keyに変更する。db-は必要な文字列みたいだから消しちゃダメ。

    <activity
      android:name="com.dropbox.client2.android.AuthActivity"
      android:launchMode="singleTask"
      android:configChanges="orientation|keyboard">
      <intent-filter>
        <!-- Change this to be db- followed by your app key -->
        <data android:scheme="db-ここをAPIキーに変更" />
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.BROWSABLE"/>
        <category android:name="android.intent.category.DEFAULT" />
      </intent-filter>
    </activity>

認証

以下のコードで認証。KEYとAccessTypeはApplicationを登録した際の設定に変更する。ActivityNameって書いてる部分は省略してthisのみとかで書くとエラーに成ったんで注意が必要。

	final static private String APP_KEY = "api-key";
	final static private String APP_SECRET = "api-secret";
	final static private AccessType ACCESS_TYPE = AccessType.DROPBOX;

	AppKeyPair appKeys = new AppKeyPair(APP_KEY, APP_SECRET);
	AndroidAuthSession session = new AndroidAuthSession(appKeys, ACCESS_TYPE);
	DropboxAPI<AndroidAuthSession> mDBApi = new DropboxAPI<AndroidAuthSession>(session);
	mDBApi.getSession().startAuthentication(ActivityName.this);

ファイル一覧を取得

DropboxAPIのmetadataでフォルダ情報を取ってきて、contents内にそのフォルダ配下のファイル情報があるからそれを取ってきてるだけ。

	List<Entry> entryList = new ArrayList<Entry>();
	try {
		Entry rootEntry = mDBApi.metadata(path, 10, null, true, null);
		List<Entry> entries = rootEntry.contents;
		for (final Entry entry : entries) {
			entryList.add(entry);
		}
	} catch (DropboxException e) {
		e.printStackTrace();
	}

Entryを表示

こんぐらいあれば表示できるようになるはず。entry.pathをmDBApi.metadata()に食わせてやればフォルダを掘っていくことができるようになる。

	for (Entry entry : entryList) {
		Log.d(TAG, entry.path); // ファイルパス
		Log.d(TAG, entry.fileName()); // ファイル名
		Log.d(TAG, String.valueOf(entry.isDir)); // エントリーがフォルダか?
	}

毎回認証が走るのがだるい

これは非常にだるいからTokenを保存して使う方法もある。

	// こんな感じで保存して
	SharedPreferences sp = getSharedPreferences('dropbox', MODE_PRIVATE);
	Editor edit = sp.edit();
	edit.putString('token', tokens.key);
	edit.putString('tokenSecret', tokens.secret);
	edit.commit();

	// こんな感じで使う
	SharedPreferences sp = getSharedPreferences('dropbox', MODE_PRIVATE);
	String accessToken = sp.getString('token', "");
	String accessTokenSecret = sp.getString('tokenSecret', "");
	AccessTokenPair tokens = new AccessTokenPair(accessToken, accessTokenSecret);
	mDBApi.getSession().setAccessTokenPair(tokens);

	// んで、認証判定して未認証なら認証開始みたいなね
	if (!mDBApi.getSession().authenticationSuccessful()) {
		mDBApi.getSession().startAuthentication(MainActivity.this);
	}

まとめ

携帯端末だと容量が少ないとかいうけど、SD使ったりすると別段そこまで気にならない。僕がDropboxを使うのは一つを修正すれば全てが変わるってところがいいんだと思う。パソコンでいじくっているものを携帯端末でちょっとだけ見れるとかそういう部分を作る際に気軽に使えるDropboxはいいよね。大体わかったからなんか作ろうかと思ってたらSyncAPIってのが出たっていうね。こっちのが便利そうだからこっちも調べてブログに書いてみようかと思う。

Dropbox – Sync API