2014年7月22日火曜日

androidとfacebookの連携を実装する 1.ログイン

android開発でfacebookと連携する機会は多いと思います。

しかし、androidアプリとfacebook SDKを使ったfacebook連携の日本語の情報は少なめです。そのうえ、facebook SDKのバージョンが古い情報ばかりがネット上だと引っかかるので以下にメモを残します。

環境

  • android4.0.2(sdk14)以上
  • facebook-android-sdk-3.15

facebook-android-sdk-3.15からはUiLifecycleHelperというactivityやfragmentのライフサイクルを管理するHelperが用意されていますが、今回は使用しません。
理由はあまり必要性を感じなかったことと、様々なactivity, fragment, dialogで実装するのには邪魔だったからです。というわけで、以下、ソースコードです。


FaceBookLogic.java

/**
 * facebook共通処理
 */
public class FaceBookLogic {
 
 public static final String TAG = "FaceBookLogic";

 /**
  * ログイン
  */
 public static final int LOGIN = 0;
 
 // アクティビティ
 private Activity mActivity;
 // 処理の種類
 private int type;
 // テキスト
 private String text;
 // 画像
 private String imagePath;
 // 画像uri
 private Uri uri;
 
 
 /**
  * 
  * @param activity Activity
  * @param type     実行種別 
  */
 public FaceBookLogic(Activity activity, int type, String text, String imagePath, Uri uri) {
  super(activity.getApplicationContext());
  mActivity = activity;
  this.type = type;
  this.text = text;
  this.imagePath = imagePath;
  this.uri = uri;
 }
 
 /**
  * Facebook認証に接続する
  * @see http://woodsmall.co.jp/android/android%E3%82%A2%E3%83%97%E3%83%AA%E3%81%ABfacebook-sdk%E3%82%92%E5%B0%8E%E5%85%A5/
  */
 public void connectFacebookAuth() {
  
  outputLog();

     Settings.addLoggingBehavior(LoggingBehavior.INCLUDE_ACCESS_TOKENS);
     
     // セッションを生成
     Session session = Session.getActiveSession();
     
     setSession(session); 
 }
 
 /**
  * セッションを設定する
  */
 private void setSession(Session session) {
     if (session == null) {
         if (session == null) {
             session = new Session(mContext);
         }
         
         // アクティブセッションとする。
         Session.setActiveSession(session);
         if (session.getState().equals(SessionState.CREATED_TOKEN_LOADED)) {
          
          // 認証を要求する。
             session.openForRead(new Session.OpenRequest(mActivity).setCallback(statusCallback));
         }
     }
     
     // ログイン状態の確認
     if (!session.isOpened()) {
      Log.d(TAG, "no login");
      facebookLogin();
     }
 }
 
 /**
  * facebookにログインする
  * @see https://groups.google.com/forum/#!topic/android-group-japan/wrxo9q-ydl0
  */
    private void facebookLogin() {
     // セッションを生成
        Session session = Session.getActiveSession();
        Log.d(TAG,"doLogin: session state is " + session.getState() + ", isOpend:" + session.isOpened() + ", isClosed:" + session.isClosed());
        if (!session.isOpened()) {
            if (session.isClosed()) {
                session = new Session(mContext);
                Session.setActiveSession(session);          
            }
            session.openForRead(new OpenRequest(mActivity).setCallback(statusCallback));
        } else {
         Log.d(TAG, "activeSession");
            Session.openActiveSession(mActivity, true, statusCallback);
        }
    }
 
    private Session.StatusCallback statusCallback = new SessionStatusCallback();
    
    private class SessionStatusCallback implements Session.StatusCallback {
        @Override
        public void call(Session session, SessionState state, Exception exception) {
         Log.d(TAG, "SessionStatusCallback");
         onSessionStateChange(session, state, exception);
        }
    }
    
    /**
     * セッションが開いた時にcallbackする
     * @param session
     * @param state
     * @param exception
     */
    private void onSessionStateChange(Session session, SessionState state, Exception exception) {
     // final Session tempSession = session;
     Log.d(TAG, "state:" + state.isOpened());
     Log.d(TAG, "session:" + session.isOpened());
     Log.d(TAG, "accessToken:" + session.getAccessToken());
        if (session.isOpened()) {
            Log.d(TAG, "Logged in...");
            
            // ログイン
            if (LOGIN == type) {
             // something
            }
            
        } else if (state.isClosed()) {
         Log.i(TAG, "Logged out...");
        }
    }
 
 
 /**
  * ログを出力
  */
 private void outputLog() {
  Log.d(TAG, "action acitivty is " + mActivity);
 }

}

呼び出し側
MainActivity.java

  FaceBookLogic logic = new FaceBookLogic(getApplicationContext());
  logic.connectFacebookAuth();
  
  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   Log.d(TAG, "onActivityResult :" + requestCode);
   Log.d(TAG, "onActivityResult resultCode:" + resultCode);
   // Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
   Log.d(TAG, "onActivityResult call:");
   switch (requestCode) {
   case REQUEST_FACEBOOK_ACCOUNT:
    if (resultCode == RESULT_OK) {
     Log.d(TAG, "facebook seceess:");
     super.onActivityResult(requestCode, resultCode, data);
     Session.getActiveSession()
     .onActivityResult(this, requestCode, resultCode, data);
    } else {
     Log.d(TAG, "facebook cancel");
     super.onActivityResult(requestCode, resultCode, data);
     Session.getActiveSession().closeAndClearTokenInformation();
    }
    break;
   }
  }


twitterなどのログインに比べると複雑です。理解するべきことはsessionの値の変化とsession取得時のcalbackの動きです。
一度立ち上げたfacebookアプリがユーザーに閉じられた場合は、セッションを切断する必要があります。*session.getActiveSession().closeAndClearTokenInformation()
でないとsessionが残ってしまい、連続でfacebookアプリを立ち上げることができなくなってしまいます。

onSessionStateChangeは、セッションの状態が変化すると呼び出されます。このメソッドの中でtokenを取得して、各アプリに必要なロジックを記述していくことになります。

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

androidでwebviewのユーザーエージェントを変更する

androidのwebviewでユーザーエージェントを変更する方法を実装したのでメモ

環境

  • android4.0.2(sdk14)以上

webviewのユーザーエージェントを変更するには、実体化したwebviewを新しいユーザーエージェントに設定するだけです。以下、ソースコードです。


  this.mWebView = (WebView) findViewById(R.id.webview);
  this.mWebView.getSettings().setUserAgentString("testagent");

setUserAgentStringメソッドで任意のユーザーエージェントを設定することが可能です。

参考サイト

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2014年7月20日日曜日

androidとtwitterを連携する 投稿機能の実装

android開発をしていると、twitterと連携して欲しいという要望は普通に出てきますね

実装したので、以下にコードを記載します。

環境

  • android4.0.2(sdk14)以上
  • twitter4j 4.0.1

連携にはtwitter4jを使います。昔からある安定したライブラリで安心して利用できます。
最初にツイートの実装です。つぶやきの文字と同時に画像も送信するようにします。以下、ソースコードです。
twitter developerの設定やoauth認証は既にできている前提です。


TwitterLogic.java

/**
 * twitterで利用するビジネスロジック
 *
 */
public class TwitterLogic {

 protected Context mContext;
 
 public TwitterLogic(Context context) {
  mContext = context;
 }
 
    /**
     * 認証されたtwitterオブジェクトを返す
     * @return
     */
    public Twitter getAuthorizedTwitter() {
     
        String token = UserTempInfo.getOAuthToken(mContext);
        String tokenSecret = UserTempInfo.getOAuthTokenSecret(mContext);
        
        Log.d("TwitterLogic", "toke n " + token);
        Log.d("TwitterLogic", "tokenSecret" + tokenSecret);

        Twitter twitter = new TwitterFactory().getInstance();
        if(twitter.getAuthorization().isEnabled()){
         Log.d("TwitterLogic", "isEnabled");
            return twitter;
        } else {
            ConfigurationBuilder builder = new ConfigurationBuilder();
            builder.setOAuthConsumerKey(mContext.getResources().getString(R.string.consumerKey));
            builder.setOAuthConsumerSecret(mContext.getResources().getString(R.string.consumerSecret));
            builder.setOAuthAccessToken(token);
            builder.setOAuthAccessTokenSecret(tokenSecret);
            Configuration configuration = builder.build();

            TwitterFactory factory = new TwitterFactory();
            try {
                twitter = factory.getInstance(new OAuthAuthorization(configuration));
            } catch (java.lang.StringIndexOutOfBoundsException e) {
                return null;
            }

            if(twitter.getAuthorization().isEnabled()){
                return twitter;
            } else {
                return null;
            }
        }
    }
    
    /**
     * シェアが成功したらtrue, それ以外はfalse
     */
    public boolean share(String msg, String imagePath) {
     
        String token = UserTempInfo.getOAuthToken(mContext);
        String tokenSecret = UserTempInfo.getOAuthTokenSecret(mContext);
        
        if (token == null || token.isEmpty() || tokenSecret == null || tokenSecret.isEmpty()) {
         Log.e(TAG, "This user is not authinticated.");
         return false;
        }

     Twitter twitter = getAuthorizedTwitter();
     if (twitter != null) {
      
      Status status = null;
      try {
    status = twitter.updateStatus(
            new StatusUpdate(msg).media("", getInputStream(imagePath)));
   } catch (TwitterException e) {
    Log.e(TAG, "twitter post error :" + e.getErrorMessage());
    return false;
   }
      
      if (status != null) {
       return true;
      }
      
      return true;
     }
     
     return false;
    }
    
    /**
     * InputStreamを取得する
     * @param imagePath 画像のurl
     * @return
     */
    public static InputStream getInputStream(String imagePath) {

  HttpURLConnection connection = null;
  InputStream in = null;
  try {
   URL url = new URL(imagePath);
   connection = (HttpURLConnection) url.openConnection();
   connection.setDoInput(true);
   connection.connect();
   in = connection.getInputStream();
  } catch (IOException e) {
   Log.e(TAG, "error occured. " + e.getMessage());
   return null;
  }
  
  return in;
    }
}


呼び出し側
MainActivity.java

  TwitterLogic logic = new TwitterLogic(mContext);
     return logic.share(mTwitterText, mImagePath);}

上記ではshareメソッドを呼び出して投稿を行っています。
画像データはinputStreamオブジェクトに変換して、mediaメソッドに設定して投稿します。
画像urlからinputStreamオブジェクトを取得するコードを書くケースは多いと思いますが、この時データは非同期で取得する必要があります。 非同期でないと、アプリがクラッシュしてしまいます。
AsyncTaskを使えばうまくいきます。

参考サイト

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2014年7月19日土曜日

androidとLineを連携する

android開発をしていると、最近はLineと連携して欲しいという要望が増えてきました。

実装したので、以下にコードを記載します。

環境

  • android4.0.2(sdk14)以上

私の場合、LineLogicというビジネスクラス用のクラスを用意しました。理由は、色々なacitivtyやfragmentで再利用したいからです。
androidとLineの連携で必要な機能は二つあります。
一つはLineのinstall有無を判断する機能。
もう一つはLineアプリにメッセージを投げるintentを取得する機能です。
以下、ソースコードです。


LineLogic.java

/**
 * SNS選択のLine選択時に利用するビジネスロジック
 */
public class LineLogic {

 protected Context mContext;
 
 public LineLogic(Context context) {
  super(context);
 }
 
 /**
  * Lineがinstall済みかどうかを判断します。
  * install済みの場合はtrue, installしていない場合はfalse
  * @return
  */
 public boolean isInstallLine() {
  // パッケージマネージャを取得
  PackageManager pm = mContext.getPackageManager();
  // ランチャーから起動出来るアプリケーションの一覧を取得
  Intent intent = new Intent(Intent.ACTION_MAIN, null);
  intent.addCategory(Intent.CATEGORY_LAUNCHER);
  // 一覧の取得
  List list = pm.queryIntentActivities(intent, 0);
  if (list != null) {
   for (ResolveInfo info : list) {
    // アプリ名をログに出力
    //Log.i("アプリ名", info.loadLabel(pm).toString());
    // パッケージ名をログに出力
    //Log.i("パッケージ名", info.activityInfo.packageName);
    // パッケージ名に「"jp.naver.line.android"」が存在するか判定
    if(info.activityInfo.packageName.equals("jp.naver.line.android")) {
     return true;
    }
      }
  }
  return false;
 }
 
 /**
  * Lineに送るintentを作成する
  */
 public Intent getIntentSendLine(String msg) {
  Intent intent = new Intent();
  intent.setAction(Intent.ACTION_VIEW);
  intent.setData(Uri.parse("line://msg/text/" + msg));
  return intent;
 }

}

呼び出し側
MainActivity.java

  LineLogic logic = new LineLogic(getApplicationContext());
  // Lineインストール済み
  if(logic.isInstallLine()) {
   startActivity(logic.getIntentSendLine("test"));
  // Line未インストール
  } else {
   // something
  }

isInstallLineメソッドでラインがinstallされているかを判断し、getIntentSendLineメソッドでメッセージを作成したintentを取得します。 このintentを投げることで、Lineにメッセージを投稿することができます。
また、isInstallLineメソッドで判定しないと、Lineアプリが未インストール時にアプリが落ちてしまいます。

参考サイト

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加
Related Posts Plugin for WordPress, Blogger...