Androidアプリから,FacebookのSDK 3.0を使う場合のTips.

Android用Facebook SDKのTips

拙作のアプリ 山旅ロガーFlash で,データをFacebookに投稿する機能を実装しました.

Facebook SDK for Android の3.0を使ったのですが,そのときに調べた内容を簡単にまとめます.

(1) Facebookアプリの存在チェック

FacebookにログインするにはFacebookアプリを呼び出すように,とのお達しなので, 端末にFacebookアプリがインストールされていない場合は,機能を使えないようにする制御を入れました.

こんな感じで,"com.facebook.katana" パッケージの有無をチェックしました.

public static boolean isFacebookAppExists(Context ctx) {
	PackageManager manager = ctx.getPackageManager();
	try {
		manager.getApplicationInfo("com.facebook.katana", 0);
	} catch (NameNotFoundException e) {
		return false;
	}
	return true;
}
本来こういうメソッドはアプリが独自実装すべきではなく,SDKが標準で持っていても良さそうなのですが,探してもどうも見あたりませんでした.

(2) Facebookログインボタンの見栄えをカスタマイズする

デフォルトではFacebookロゴの青い画像のボタンです.

ただしうちのアプリでは標準パーツで画面を組み立てているため,この青い画像は浮いてしまいます.

それで,これをButton標準パーツの見栄えに変更したいと思ってソースを見ると

FacebookSDK/src/com/facebook/widget/LoginButton.java L.200-

if (attrs.getStyleAttribute() == 0) {
        // apparently there's no method of setting a default style in xml,
        // so in case the users do not explicitly specify a style, we need
        // to use sensible defaults.
        ・・・
        this.setBackgroundResource(R.drawable.com_facebook_loginbutton_blue);
LoginButtonにstyle属性が設定されていない場合に青い画像を設定しているため, アプリ側のlayout xmlで何らかのstyle属性を設定しておけば,青い画像は設定されないように見えます.

それでこんな感じで,アプリ側のlayout xmlにでたらめなstyle属性値を設定してみました.

<com.facebook.widget.LoginButton
    android:id="@+id/btnFbLogin"
    style="@string/app_name"
    ・・・
すると,確かに見栄えは通常のボタンに変わったのですが,以下のカスタマイズ項目が無視されるようになってしまいました.orz
facebook:confirm_logout="false"
facebook:fetch_user_info="false"
facebook:login_text="Facebookにログイン"
facebook:logout_text="Facebookからログアウト"
それでまた先ほどのソースを見ると,style属性がある場合には,
parseAttributes(attrs);
を呼び出さないようになっていました.そのためカスタマイズ項目が無視されるようです.

...結局,こんな風にソースを変更して対応しました.

FacebookSDK/src/com/facebook/widget/LoginButton.java L.197-

public LoginButton(Context context, AttributeSet attrs) {
    super(context, attrs);

    if (attrs.getStyleAttribute() == 0) {
            ・・・そのまま・・・
    } else {
        // デフォルトの青いスタイルを使いたくない場合でも,
        // login_textなどの属性を上書き可能にする
        parseAttributes(attrs);
    }
}

アプリ側のlayout xmlでのログインボタン記述は,こんな感じです.styleの値は適当ですので参考にしないで下さい.

<com.facebook.widget.LoginButton
    android:id="@+id/btnFbLogin"
    style="@string/app_name"
    facebook:confirm_logout="false"
    facebook:fetch_user_info="false"
    facebook:login_text="Facebookにログイン"
    facebook:logout_text="Facebookからログアウト"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

(3) 画像とコメントを一緒に投稿する

Facebookに画像,写真を投稿するメソッド
com.facebook.Request.newUploadPhotoRequest()
はあるのですが,画像とコメントを同時に投稿できるメソッドは無いんですよね.

仕方がないので,同じRequestクラスにこんなメソッドを追加して対応しました.

FacebookSDK/src/com/facebook/Request.java に追加

public static Request newUploadPhotoMessageRequest(Session session, File file, String message,
        Callback callback) throws FileNotFoundException {
    ParcelFileDescriptor descriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
    Bundle parameters = new Bundle(2);
    parameters.putParcelable(PICTURE_PARAM, descriptor);
    parameters.putString("caption", message);

    return new Request(session, MY_PHOTOS, parameters, HttpMethod.POST, callback);
}
やっていることは,既存の画像投稿メソッドに,内部パラメータcaptionの設定を追加しただけです.

(4) バックグラウンドから投稿する

Activityから投稿するのはサンプルもあって簡単なのですが,Activity以外から投稿するのに難航しました.

具体的には,ContentProviderからnewしたバックグラウンドスレッドからの投稿です.

これは,完全には解決できていません.

以下の実装で動いてはいますが,セッションの期限切れのような状態で失敗する場合があり,不完全です.

String message = "TEST";
Request request = Request.newStatusUpdateRequest(Session.getActiveSession(), message, null);
// バックグラウンドなので同期実行しても良い
Response response = request.executeAndWait();
boolean success = (response.getError() == null);

(5) SDK既存バグの修正

Facebookのログイン画面でキャンセルするとヌルポ.
 →FacebookSDK/src/com/facebook/AuthorizationClient.java を修正します.

(6) API Levelを下げる

SDKそのままだと,minSdkVersionが8(Android 2.2)です.

これでいいならこのままで良いと思いますが,うちは5(Android 2.0)まで下げました.

5に下げた状態でlintをかけた時に発生するエラーで修正箇所はわかりますが, @Deprecatedでかつ実際にも使われていないメソッドで発生しているものが多く,それらはメソッドごとコメントアウトしました.

若干微妙な箇所で,ここがありましたが,

FacebookSDK/src/com/facebook/widget/WebDialog.java L.344-

@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
    super.onReceivedSslError(view, handler, error);

    sendErrorToListener(new FacebookDialogException(null, ERROR_FAILED_SSL_HANDSHAKE, null));
    handler.cancel();
    WebDialog.this.dismiss();
}
このonReceivedSslErrorメソッド(v8)でハンドリングしなくても実害はないと判断して, このメソッドもコメントアウトしてしまいました.

(7) proguard (2013/4/7 追記)

それなりにハマりました.
  • アプリのプロジェクトに libs\android-support-v4.jar を配置する
  • アプリのプロジェクトのtargetSdkを,Lv16(4.1)以上に上げる (minSdkとは別の話です.ちなみにうちのアプリでは android:minSdkVersion="4" android:targetSdkVersion="16" にしています)
  • アプリのproguard.cfg に以下を追加する
-libraryjars \libs\android-support-v4.jar
-dontwarn **CompatHoneycomb
-dontwarn **CompatCreatorHoneycombMR2
-dontwarn android.support.v4.view.**
-keep class android.support.v4.** { *; }
-keep class com.facebook.** { *; }
-keep class android.webkit.WebViewClient
-keep class * extends android.webkit.WebViewClient
-keepclassmembers class * extends android.webkit.WebViewClient { 
    <methods>; 
}
-keepattributes Signature
あと,Facebookの管理画面でリリースビルドでのハッシュキーを追加するのも忘れずに.FBへのログイン時に署名チェックエラーが出るのでわかると思いますが

参考リンク


© 2024 KMIソフトウェア