AndroidでFB、VK、G +を接続します。 ライトバージョン

私が直面した課題は、Androidからいくつかのソーシャルネットワークへのリンクを投稿することでした。 さらに、エンティティを生成せず、トークン、セッションなどに煩わされないように、できるだけシンプルで簡単です。 実際、タスクは最小限です-ユーザー自身のアカウントにリンクを配置するだけです。 リンクに簡単に説明や写真を追加できる場合は、それを行いますが、休まないでください。



さまざまな理由から、Facebook、Vkontakte、およびGoogle+が選ばれました。 私はTwitterを追加する予定でしたが、そのFabricはまだリリースされていなかったため、サードパーティのライブラリを使用したくありませんでした(下記の条項2を参照)。 後で追加します。



その結果、これら3つのソーシャルネットワークのタスクは次のとおりでした。



  1. リンクを投稿するための最も簡単なプログラミングインターフェイス。
  2. ネイティブSDKのみを使用する(この知識が後で役立つようになるため)。
  3. 最小限のコードは、作業に最も必要なだけです。
  4. ユーザーがソーシャルネットワーククライアントをインストールしているかどうかに関係なく、すべてが機能するはずです。 ただし、ある場合は、クライアントダイアログを使用します。
  5. ユーザーは、投稿の成功または失敗に関するメッセージを受信する必要があります。
  6. 投稿の成功にプログラムで対応できるようにする必要があります。




ソリューションのアーキテクチャ



最終的に別のライブラリを使用するオプションは面倒であることが判明しました。最終的なコードはコメントと空白行とともに約250行でした。 さらに、すべてが1つのクラスにカプセル化されており、非常に簡単に使用できます。



SDKの多数のオブジェクトをライフサイクルに組み込む必要があったため、アクティビティまたはフラグメントのいずれかのコンテナが必要でした。 私は抽象的なアクティビティを備えたソリューションを選択しました。 ActionBarボタンに投稿コマンドを掛ける必要がありました。 さらに、異なるフラグメントを内部に持ついくつかのアクティビティに対してこれを行うこと。



抽象アクティビティでは、すべての投稿管理コードを作成し、3つのメソッド(グリッドごとに1つ)を作成しました。 この同じAbstract Activityから、ソーシャルネットワークが必要とされた残りのActivityアプリケーションを後に継承しました。 それらでは、目的のコードへのアクセスは、親クラスからのメソッド呼び出しに限定されていました。



ここで説明されていることはすべて、フラグメントを使用して確実に実行できます。 どこかで、親アクティビティに対してライフサイクルへの埋め込みを行う必要があるというメッセージに出会いましたが。 知らない、試したことがありません。



だから...



以下で説明するコードを機能させるには、SDKを各ソーシャルネットワークのプロジェクトに接続し、開発者セクションでアプリケーションを登録する必要があります。 すべてをここで説明します。



開発中、SDKの説明はソーシャルネットワークのネイティブサイト、HabréとSOに関する記事、ASNEライブラリコードで使用されました(著者のおかげです!)



Google+



最も単純なコードは、G +の論理ソリューションです。 認証とセッションに関するすべての機能は、すでにシステムに組み込まれています。 目的のダイアログボックス(クライアントが存在しない場合はクライアントまたはWebからのネイティブ)が単独で選択され、成功した投稿についてレポートされます。 ここで最後のものは唯一の待ち伏せでした-要件の条項6の実装。 パブリケーションの成功を追跡するには、onActivityResultに1つの定数と1つの条件ステートメントを追加する必要がありました。



private static final int GOOGLEPLUS_REQUEST_CODE = 1001; protected void onActivityResult(int requestCode, int resultCode, Intent data) { ... if ((requestCode == GOOGLEPLUS_REQUEST_CODE) && (resultCode == -1)) { //Do something if success } }
      
      





転記手順自体:



  /** * Publish link in Google+ * @param text - message about link (may be changed or deleted by user) * @param link - http:// etc */ public final void googleplusPublish(String text, String link) { Intent shareIntent = new PlusShare.Builder(this) .setType("text/plain") .setText(text) .setContentUrl(Uri.parse(link)) .getIntent(); startActivityForResult(shareIntent, GOOGLEPLUS_REQUEST_CODE); }
      
      





フェイスブック



Facebookをもっといじる必要がありましたが、すべての要件が実装されていませんでした。



判明した:



うまくいきませんでした:



コードに含まれるもの...



まず、string.xmlにアプリケーション識別子を追加し、マニフェストにメタデータを入力する必要があります(インターネットへのアクセスを許可することを忘れずに-これはすべてのネットワークに必要です!):



  <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
      
      





作業には、ライフサイクルメソッドに非常に密接に関係する補助オブジェクトが必要です。 ネイティブクライアントがインストールされている場合、ネイティブクライアントによる投稿に必要です。 もちろん、Webだけを実行することもできますが、セッションがないと毎回パスワードが必要になり、非常に面倒です。 そして、再びユーザーを悩ますのは良くありません...



出版の成功を追跡するには、ペンで書く必要がありました。 これは同じことがクライアントでクラッシュした場所です:



  private UiLifecycleHelper fbUIHelper; protected void onCreate(Bundle savedInstanceState) { ... fbUIHelper = new UiLifecycleHelper(this, null); fbUIHelper.onCreate(savedInstanceState); } protected void onActivityResult(int requestCode, int resultCode, Intent data) { ... fbUIHelper.onActivityResult(requestCode, resultCode, data, new FacebookDialog.Callback() { //Listener for Facebook-client if installed @Override public void onError(FacebookDialog.PendingCall pendingCall, Exception error, Bundle data) { toastMessage("  "); } @Override public void onComplete(FacebookDialog.PendingCall pendingCall, Bundle data) { toastMessage("     ,   "); } }); protected void onResume() { ... fbUIHelper.onResume(); } protected void onSaveInstanceState(Bundle outState) { ... fbUIHelper.onSaveInstanceState(outState); } protected void onPause() { ... fbUIHelper.onPause(); } protected void onDestroy() { ... fbUIHelper.onDestroy(); }
      
      





子クラスで使用されるメソッドコード自体は次のとおりです。



  /** * Publish link in FaceBook * @param name - title of block * @param caption - text on bottom of block * @param description - description of link (between title and caption) * @param link - http:// etc * @param pictureLink - http:// etc - link on image in web */ public final void facebookPublish(String name, String caption, String description, String link, String pictureLink) { if (FacebookDialog.canPresentShareDialog(getApplicationContext(), FacebookDialog.ShareDialogFeature.SHARE_DIALOG)) { //Facebook-client is installed FacebookDialog shareDialog = new FacebookDialog.ShareDialogBuilder(this) .setName(name) .setCaption(caption) .setDescription(description) .setLink(link) .setPicture(pictureLink) .build(); fbUIHelper.trackPendingDialogCall(shareDialog.present()); } else { //Facebook-client is not installed – use web-dialog Bundle params = new Bundle(); params.putString("name", name); params.putString("caption", caption); params.putString("description", description); params.putString("link", link); params.putString("picture", pictureLink); WebDialog feedDialog = new WebDialog.FeedDialogBuilder(this, Utility.getMetadataApplicationId(this), params) .setOnCompleteListener(new OnCompleteListener() { //Listener for web-dialog @Override public void onComplete(Bundle values, FacebookException error) { if ((values != null) && (values.getString("post_id") != null) && (error == null)) { toastMessage(" "); } else { toastMessage("  "); }; }; }) .build(); feedDialog.show(); } }
      
      





VKontakte



おそらく最も不気味なドキュメント。 かなり汗をかかなければなりませんでした。 さらに、トークンの使用を完全になくすことはできませんでした。 しかし、順番に...



ここでは、1行のコードのためにマニフェストに入る必要があります。



  <activity android:name="com.vk.sdk.VKOpenAuthActivity"/>
      
      





ドックでは、「 追加する価値あります。そうしないと承認アクティビティを開始する際に問題発生する可能性あります静かに書かれていますが、ユーザーがVKクライアントを持っていない場合、アプリケーションはActivityNotFoundExceptionエラーでクラッシュします。



クラス自体の最初に、ID、アクセス権、および許可制御を保存するコードを追加する必要があります。



  private String appId = "1234567"; // Need to change to real app_id private static String vkTokenKey = "VK_ACCESS_TOKEN"; private static String[] vkScope = new String[]{VKScope.WALL}; private final VKSdkListener vkSdkListener = new VKSdkListener() { @Override public void onCaptchaError(VKError captchaError) { new VKCaptchaDialog(captchaError).show(); } @Override public void onTokenExpired(VKAccessToken expiredToken) { VKSdk.authorize(vkScope, true, false); } @Override public void onAccessDenied(VKError authorizationError) { new AlertDialog.Builder(SocialNetworkActivity.this) .setMessage(authorizationError.errorMessage) .show(); } @Override public void onReceiveNewToken(VKAccessToken newToken) { newToken.saveTokenToSharedPreferences(getApplicationContext(), vkTokenKey); } };
      
      





この感染は、FBほどではありませんが、アクティビティライフサイクルの方法にも深く浸透しています。



  protected void onCreate(Bundle savedInstanceState) { ... VKUIHelper.onCreate(this); VKSdk.initialize(vkSdkListener, appId, VKAccessToken.tokenFromSharedPreferences(this, vkTokenKey)); } protected void onActivityResult(int requestCode, int resultCode, Intent data) { ... VKUIHelper.onActivityResult(this, requestCode, resultCode, data); } protected void onResume() { ... VKUIHelper.onResume(this); } protected void onDestroy() { ... VKUIHelper.onDestroy(this); }
      
      





ただし、リンクを公開するときは、ユーザーに最初にログインさせ、次に公開ボタンを再度クリックする必要があります。 これは使いやすさの観点からは悪いことですが、別の選択肢は見つかりませんでした。 一度発行されたトークンは約1時間機能するようです。 出血しますが、FB Webダイアログのように、各投稿に登録するよりも悪くはありません。



別の待ち伏せは、セットアップを期待していなかったところに潜んでいました。 実際のデバイスでEclipseからデバッグする場合、すべてが時計のように機能しました。 しかし、Google Playから同じアプリケーションをインストールするとすぐに、VKクライアントはリンクを投稿するときに呪いを開始しました。



{「エラー」:「invalid_request」、「error_description」:「sdk_fingerprintが正しくありません」}



さらに、認証は成功し、Webを介したVKクライアントなしの同じアプリケーションは正常に動作します。 つまり 指紋は正しいです。 クライアントの不具合が疑われる。 または、グリッチではなく、意図的に閉じられた機会であり、 このリンクを見る可能性が非常に高い(最後に近い)。 私はさらに理解しますが、誰かが知っていて助けてくれるなら、私は感謝します。



別の未解決の質問は、プレビューウィンドウに表示されるリンクタイトルが公開時に失われる理由です。 悲しいかな、答えが見つかりませんでした。 ヒントにも感謝します。



投稿コード自体:



  /** * Publish link in Vkontakte * @param message - message about link (may be changed or deleted by user) * @param link - http:// etc * @param linkName - title of link - not published (don't know why...) */ public final void vkontaktePublish(String message, String link, String linkName) { VKAccessToken token = VKAccessToken.tokenFromSharedPreferences(this, vkTokenKey); if ((token == null) || token.isExpired()) { VKSdk.authorize(vkScope, true, false); toastMessage(" .     "); } else { new VKShareDialog() .setText(message) .setAttachmentLink(linkName, link) .setShareDialogListener(new VKShareDialog.VKShareDialogListener() { @Override public void onVkShareComplete(int postId) { toastMessage(" "); } @Override public void onVkShareCancel() { toastMessage("  "); } }).show(getSupportFragmentManager(), "VK_SHARE_DIALOG"); } }
      
      





サポートライブラリの下にアプリケーションを作成したため、コードではgetSupportFragmentManagerを使用します。 バージョン3.0以降では、ネイティブメソッドの呼び出しに置き換える必要があります。



コードの使用



まあ、それはすべて簡単です。 ここから目的のアクティビティを継承し、必要な場合はxxxPublish()呼び出しを使用します。 ボタンを切るか、ActionBarでポップアップメニューを使用することもできます(ただし、この場合、呼び出しはあまり美しくありませんが、メニュー自体は機能しています)。



  public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_share: View view = findViewById(R.id.action_share); showPopupMenu(view, "https://play.google.com/store/apps/details?id=ru.fantaversum.taleidoscope", " -   ", "  Google Play", "      -     .   .  .", "http://www.taleidoscope.ru/images/fb_logo.png", ":  -  .       -     .   .  .", "  Google Play"); break; } return super.onOptionsItemSelected(item); }
      
      





  public void showPopupMenu(View view, final String link, final String fb_name, final String fb_caption, final String fb_description, final String fb_pictureLink, final String message, final String linkName) { PopupMenu popup = new PopupMenu(this, view); popup.getMenuInflater().inflate(R.menu.popup, popup.getMenu()); popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { switch (menuItem.getItemId()) { case R.id.menu_facebook: facebookPublish(fb_name, fb_caption, fb_description, link, fb_pictureLink); return true; case R.id.menu_vkontakte: vkontaktePublish(message, link, linkName); return true; case R.id.menu_googleplus: googleplusPublish(message, link); return true; } return false; } }); popup.show(); }
      
      





アクティビティ全体のソースコードは、 ここからダウンロードできます



All Articles