編輯:關於Android編程
最近公司的軟件需要改國際版,需要Facebook和Twitter的登錄和分享。
本人先用Umeng的第三方社會化分享實現了該功能,但是後來一想問題來了,經過查證。Umeng只在中國和美國有服務器,那也就是說別的國家的人如果用該產品登錄和分享可不就成了擺設,這下苦逼了,然後就又重新推倒重來,索性用官方的facebook和twitter來實現登錄和分享。具體步驟:
第一,因為中國政府各種坑比牆國外的服務器,導致facebook和twitter訪問不了,那第一步就需要翻牆,順便翻牆看看蒼老師什麼的,,,,我在網上找到了一個比較好的翻牆軟件:藍燈(Lantern)進入該網站,本人下載了mac版本。順便做下載了對應的android apk,用法很簡單。安裝上之後開啟就行了,這樣你就能訪問蒼老師,天海翼了
第二步:既然咱們成功翻牆了,那就開始咱們的步伐:
Facebook登錄和分享
咱們先進入facebook的官網
然後注冊賬號。我使用郵箱注冊的,注冊完成之後就可以創建項目了
因為我已經創建過,所以這塊就各位自己操作就行,
然後咱們要做的就是看文檔。
進入此網站就可以看到facebook其實寫的已經很清楚了:https://developers.facebook.com/docs/facebook-login/android
因為facebook官網下載的sdk後綴名是(.aar)的,不是咱們正常的jar包,所以我索性就在Android studio中找jar包,就是如上圖所示。
然後只需要按照facebook文檔中的步驟往下就可以了
-------------------------------------------------------------------facebook文檔開始-----------------------------------------------------------
點擊下方的按鈕,下載 Facebook 應用。
下載 Android 版 Facebook如果沒有 Facebook 開發者帳戶,請點擊下面的按鈕創建。您可以通過 Facebook 開發者帳戶使用開發者工具和創建 Facebook 應用。
創建開發者帳戶下載最新的 Android 版 Facebook SDK。
下載 Android SDK點擊下方的按鈕,按照快速入門操作,也可以按照新手入門中的步驟操作。
Android 快速入門為應用啟用單點登錄的方法是:在 Facebook 開發者網站的我的應用中選擇您的應用,然後選擇應用的設置,並將單點登錄設置為是。
將 Facebook 登錄添加到應用的最簡單方法是從 SDK 添加LoginButton。這是Button的自定義視圖實施。您可以在應用中使用該按鈕實施 Facebook 登錄。
您可以結合LoginButton使用 SDK 提供的以下類:
LoginButton是一個界面元素,其中包含LoginManager具備的功能。因此,當用戶點擊此按鈕時,就會以LoginManager中設置的權限開始登錄。按鈕隨登錄狀態變化,並根據用戶的身份驗證狀態顯示正確文本。
要添加 Facebook 登錄按鈕,請先將其添加到布局 XML 文件中,並使用完整的類名稱com.facebook.widget.LoginButton:
然後在界面中設置按鈕:將按鈕添加到片段中,並更新活動以使用片段。
您可以自定義Login button的屬性,並在onCreateView()方法中注冊一個回調。
您可以自定義的屬性包括LoginBehavior、DefaultAudience、ToolTipPopup.Style以及LoginButton的相關權限。例如:
@Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.splash, container, false); loginButton = (LoginButton) view.findViewById(R.id.login_button); loginButton.setReadPermissions("email"); // If using in a fragment loginButton.setFragment(this); // Other app specific specialization // Callback registration loginButton.registerCallback(callbackManager, new FacebookCallback() { @Override public void onSuccess(LoginResult loginResult) { // App code } @Override public void onCancel() { // App code } @Override public void onError(FacebookException exception) { // App code } }); }
如果您在片段中使用LoginButton,需要通過調用setFragment來設置按鈕上的片段,如圖所示。
之後您需要調用FacebookSdk.sdkInitialize來初始化 SDK,然後調用CallbackManager.Factory.create來創建回調管理器,以便處理登錄響應。以下是在片段中添加回調的示例:
public class MainActivity extends FragmentActivity { CallbackManager callbackManager; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); FacebookSdk.sdkInitialize(getApplicationContext()); callbackManager = CallbackManager.Factory.create(); LoginButton loginButton = (LoginButton) view.findViewById(R.id.usersettings_fragment_login_button); loginButton.registerCallback(callbackManager, new FacebookCallback() { ... }); }
最後您應調用callbackManager.onActivityResult,以便通過callbackManager將登錄結果傳遞至LoginManager。
為了響應登錄結果,您需要使用LoginManager或LoginButton注冊回調。如果您使用LoginButton注冊回調,就不需要在登錄管理器中注冊回調。
將回調添加到活動或片段的onCreate()方法:
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); FacebookSdk.sdkInitialize(this.getApplicationContext()); callbackManager = CallbackManager.Factory.create(); LoginManager.getInstance().registerCallback(callbackManager, new FacebookCallback() { @Override public void onSuccess(LoginResult loginResult) { // App code } @Override public void onCancel() { // App code } @Override public void onError(FacebookException exception) { // App code } }); }
如果登錄成功,LoginResult參數將擁有新的AccessToken及最新授予或拒絕的權限。
您不需要registerCallback來保證登錄成功,可以選擇使用下述AccessTokenTracker類跟蹤當前訪問口令的更改。
之後在onActivityResult()中,將登錄結果轉發到在onCreate()中創建的callbackManager:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); callbackManager.onActivityResult(requestCode, resultCode, data); }
您集成到 FacebookSDK 登錄或分享的所有活動和片段都應將onActivityResult轉發給 callbackManager
-------------------------------------------------------------------facebook文檔結束------------------------------------------------
如上的步驟就可以了嗎?答案是NO,原因是因為我們還沒有配置SDK。那我們就接著配置Facebook的SDK呗。
然後一定需要配置SDK,一定要配置Key Hashes。否則當您授權時就會出現錯誤。
所提供的網址不被應用程序配置所接納
配置完之後我們就可以登錄授權Facebook了。 然後開始看我寫的代碼: 在您的Application活著是第一個界面中添加如下代碼,就實現了Facebook和Twitter的初始化。FacebookSdk.sdkInitialize(getApplicationContext()); AppEventsLogger.activateApp(this); TwitterAuthConfig authConfig = new TwitterAuthConfig(TWITTER_KEY, TWITTER_SECRET); Fabric.with(this, new Twitter(authConfig)); try { //facebook獲取測試包的SHA秘鑰 PackageInfo info = getPackageManager().getPackageInfo( "com.dora.feed", PackageManager.GET_SIGNATURES); for (Signature signature : info.signatures) { MessageDigest md = MessageDigest.getInstance("SHA"); md.update(signature.toByteArray()); SysoutUtil.out("KeyHash:" + Base64.encodeToString(md.digest(), Base64.DEFAULT)); } } catch (PackageManager.NameNotFoundException e) { } catch (NoSuchAlgorithmException e) { }
/** * FaceBook登錄 */ public void LoginFaceBook(){ List在點擊Facebook登錄按鈕的地方調用此方法就可以實現登錄了,並且能獲取到您需要的用戶信息 接著我們需要回調,如下:permissions = Arrays.asList("public_profile", "user_friends", "user_status"); LoginManager.getInstance().logInWithReadPermissions(activity, permissions); LoginManager.getInstance().registerCallback(callbackManager, new FacebookCallback () { @Override public void onSuccess(LoginResult loginResult) { // App code SysoutUtil.out("logingResult:" + loginResult); AccessToken accessToken = loginResult.getAccessToken(); GraphRequest request = GraphRequest.newMeRequest(accessToken, new GraphRequest.GraphJSONObjectCallback() { @Override public void onCompleted(JSONObject object, GraphResponse response) { //獲取登錄成功之後的用戶詳細信息 SysoutUtil.out("JSONObject:" + object); String facebook_id = object.optString("id"); String facebook_name = object.optString("name"); String picture = object.optString("picture"); String imageUrl = null; try { JSONObject jsonObject = new JSONObject(picture); String data = jsonObject.getString("data"); imageUrl = new JSONObject(data).getString("url"); } catch (JSONException e) { e.printStackTrace(); } } }); //包入你想要得到的資料 送出request Bundle parameters = new Bundle(); parameters.putString("fields", DEFAULT_REQUEST_VALUE); request.setParameters(parameters); request.executeAsync(); } @Override public void onCancel() { SysoutUtil.out("onCancel:"); } @Override public void onError(FacebookException exception) { // App code SysoutUtil.out("onError:"); } }); }
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(callbackManager != null){ //facebook的回調 callbackManager.onActivityResult(requestCode, resultCode, data); } if(loginButton != null){ //twitter的回調 loginButton.onActivityResult(requestCode, resultCode, data); } SysoutUtil.out("data:" + data); }到此facebook的登錄就完成了!!!!! 然後我們再看分享的具體代碼實現,如下:
/** * 分享到facebook */ private CallbackManager callBackManager; public void shareFaceBook() { Bitmap image = BitmapFactory.decodeResource(getResources(), com.dora.feed.R.drawable.app_logo); callBackManager = CallbackManager.Factory.create(); new FaceBookShareUtils(this,callBackManager,facebookCallback) .share(getResources().getString(R.string.app_name), image, getResources().getString(R.string.share_tips_tips)); }
package com.dora.feed.utils; /** * Created by wangkai on 16/9/3. */ import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import com.dora.feed.net.Api; import com.facebook.CallbackManager; import com.facebook.FacebookCallback; import com.facebook.share.ShareApi; import com.facebook.share.model.ShareHashtag; import com.facebook.share.model.ShareLinkContent; import com.facebook.share.model.SharePhoto; import com.facebook.share.model.SharePhotoContent; import com.facebook.share.widget.ShareDialog; /** * facebook分享工具類 * Created by Song on 2016/7/5. * Email:[email protected] */ public class FaceBookShareUtils { private Activity mActivity ; private ShareDialog shareDialog; private CallbackManager callBackManager; public static final int SHARE_REQUEST_CODE = 10010; private ShareLinkContent.Builder shareLinkContentBuilder; public FaceBookShareUtils(Activity activity, CallbackManager callBackManager, FacebookCallback facebookCallback) { this.mActivity = activity ; this.callBackManager = callBackManager; shareDialog = new ShareDialog(mActivity); //注冊分享狀態監聽回調接口 shareDialog.registerCallback(callBackManager, facebookCallback, FaceBookShareUtils.SHARE_REQUEST_CODE); shareLinkContentBuilder = new ShareLinkContent.Builder(); } /** * 分享 */ public void share(String contentTitle,String imageUrl,String desc) { shareLinkContentBuilder.setContentTitle(contentTitle) .setImageUrl(Uri.parse(imageUrl)) .setContentDescription(desc) .setContentUrl(Uri.parse(Api.SHARE_LEFT_URL)); ShareLinkContent shareLinkContent = shareLinkContentBuilder.build(); if(shareDialog.canShow(ShareLinkContent.class)) { shareDialog.show(mActivity,shareLinkContent); } } /** * 分享 */ public void share(String contentTitle, Bitmap imageUrl,String desc) { // SharePhoto photo = new SharePhoto.Builder() // .setBitmap(imageUrl) // .setCaption(desc) // .build(); // // SharePhotoContent content = new SharePhotoContent.Builder() // .addPhoto(photo) //// .setContentUrl(Uri.parse(Api.SHARE_LEFT_URL)) // .build(); // // ShareApi.share(content, null); // if(shareDialog.canShow(SharePhotoContent.class)) { // shareDialog.show(mActivity,content); // } if (shareDialog.canShow(ShareLinkContent.class)) { ShareLinkContent linkContent = new ShareLinkContent.Builder() .setContentTitle(contentTitle) .setContentDescription(desc) .setContentUrl(Uri.parse(Api.SHARE_LEFT_URL)) // .setImageUrl(Uri.parse("android.resource://de.ginkoboy.flashcards/" + com.dora.feed.R.drawable.app_logo)) .setImageUrl(Uri.parse("http://bagpiper-andy.de/bilder/dudelsack%20app.png")) .build(); shareDialog.show(linkContent); } } }
/** * facebook分享狀態回調 */ private FacebookCallback facebookCallback = new FacebookCallback() { @Override public void onSuccess(Object o) { SysoutUtil.out("onSuccess" + o.toString()); // Message msg = Message.obtain(); // msg.what = SHARE_COMPLETE; // mHandler.sendMessage(msg); } @Override public void onCancel() { SysoutUtil.out("onCancel"); // Message msg = Message.obtain(); // msg.what = SHARE_CANCEL; // mHandler.sendMessage(msg); } @Override public void onError(FacebookException error) { SysoutUtil.out("onError"); ToastUtils.showToast("share error--" + error.getMessage()); // Message msg = Message.obtain(); // msg.what = SHARE_ERROR; // mHandler.sendMessage(msg); } };
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if(PromptUtils.isProgressDialogShowing()){ PromptUtils.dismissProgressDialog(); } if(FaceBookShareUtils.SHARE_REQUEST_CODE == requestCode) { callBackManager.onActivityResult(requestCode,resultCode,data); }else if(requestCode == TWEET_COMPOSER_REQUEST_CODE){ SysoutUtil.out("onActivityResult"); ToastUtils.showToast("share success"); } // callBackManager.onActivityResult(requestCode,resultCode,data); }
Twitter本人研究了三天,看各種文檔,twitter的源碼,最後才實現了
首先還是看文檔:
Twitter的文檔很不好找,https://www.fabric.io/kits/android/twitterkit/install
在文檔中可以很清楚的看到,應該如何配置Fabric
看我的代碼具體實現:
首先配置項目的build.gradle(也就是最外邊的一個gradle)
// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { jcenter() maven { url 'https://maven.fabric.io/public' } } dependencies { classpath 'com.android.tools.build:gradle:1.5.0' classpath 'io.fabric.tools:gradle:1.+' } } allprojects { repositories { jcenter() } } task clean(type: Delete) { delete rootProject.buildDir }
其次是配置您的應用的 module的build.gradle
apply plugin: 'com.android.application' // This does not break the build when Android Studio is missing the JRebel for Android plugin. apply plugin: 'io.fabric' repositories { maven { url 'https://maven.fabric.io/public' } } android { compileSdkVersion 23 buildToolsVersion '23.0.1' defaultConfig { applicationId "com. aaa.feed" minSdkVersion 17 targetSdkVersion 23 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } // productFlavors.all { // flavor -> flavor.manifestPlaceholders = [CHANEL_ID_VALUE: name] // } lintOptions { abortOnError false } dataBinding { enabled = true } } dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') compile project(':famlinkFrame') compile project(':PushSDK') compile 'tv.danmaku.ijk.media:ijkplayer-java:0.5.1' compile('com.twitter.sdk.android:twitter:2.0.0@aar') { transitive = true; } compile('com.twitter.sdk.android:tweet-composer:0.9.0@aar') { transitive = true; } }然後重新clear您的Android studio,這樣Fabric就可以自動下載twitter的jar包了。
下載完成之後咱們要做的就是開始寫代碼:
Twitter的初始化在前邊的代碼中已經有體現。
/** * Twitter登錄 */ private void LoginTwitter(){ loginButton.setCallback(new Callback() { @Override public void success(Result result) { TwitterApiClient twitterApiClient = TwitterCore.getInstance().getApiClient(); Call call = twitterApiClient.getAccountService().verifyCredentials(false, false); call.enqueue(new Callback () { @Override public void success(Result result) { String dataResult = "Name: " + result.data.name + "\nScreenName: " + result.data.screenName + "\nProfileImage: " + result.data.profileImageUrl + "\nBackgroungUrl" + result.data.profileBannerUrl + "\nCreated at" + result.data.createdAt + "\nDescription" + result.data.description + "\nEmail" + result.data.email+ "\nFriends Count" + result.data.friendsCount; System.out.println(result.data.profileImageUrl); String twitter_id = String.valueOf(result.data.id); String twitter_name = result.data.name; CacheUtils.getInstance().putString(LocalContents.ACCESS_TOKEN, "twitter"+twitter_id); String[] str = {twitter_name, result.data.profileImageUrl}; CacheUtils.getInstance().putString(LocalContents.LOGIN_USER_NAME, str[0]); CacheUtils.getInstance().putString(LocalContents.LOGIN_USER_HEAD, str[1]); DataChangeNotification.getInstance().notifyDataChanged(IssueKey.CLOSE_LOGIN_ACTIVITY); DataChangeNotification.getInstance().notifyDataChanged(IssueKey.UPDATEHEAD, str); // TwitterAuthToken token = session.getAuthToken(); } @Override public void failure(TwitterException exception) { System.out.println(exception.getMessage()); } }); } @Override public void failure(TwitterException exception) { SysoutUtil.out("TwitterKit" + "Login with Twitter failure" + exception); } });
到此處登錄就完成了,並且您的頭像以及各種信息都能取到,本人逛了很多國外網站都說通過 接口的形式來重新獲取用戶信息,然後twitter官方也建議這麼做,但是在我用的時候接口一直返回“215”,本人試了不下上百次,把該接口各種配置,但是怎麼都返回215,215的大致意思是我需要重新驗證身份,那我就想不通了,我再登錄之前肯定驗證身份了,不知道是為啥,最後我實在崩潰了;
我就想既然這種方法實現不了,那我就換種思路,程序員最重要的一點就是要能看代碼,那我索性就看twitter jar包的源碼了,果然看源碼還是很有用的,最後發現twitter中的用戶信息存儲在User類下,然後我只需要獲取到User的數據不就行了,然後就是一步一步的開始看源碼,最後終於找到解決方案了如下圖,
到此為止,我們的登錄就算完整了,用戶的所有信息想怎麼取就怎麼取。
最後我們在做分享
分享很簡單,我就不做解釋了,直接將本方法拷入代碼,調用就可以:
/** * 分享到Twitter * @throws MalformedURLException */ private void shareTweet() throws MalformedURLException { // final long tweetId = 771558172175716352L; // TweetComposer.Builder builder = new TweetComposer.Builder(this) // .text(getResources().getString(R.string.share_tips_tips)) // .url(new URL(Api.SHARE_LEFT_URL)); // Intent intent = builder.createIntent(); // builder.show(); // startActivityForResult(intent, 1000); Intent intent = null; try { intent = new TweetComposer.Builder(this) .text("標題") .url(new URL("您的URL")) .image(getHeaderIconUri()) .createIntent(); } catch (MalformedURLException e) { e.printStackTrace(); } startActivityForResult(intent, TWEET_COMPOSER_REQUEST_CODE); } public Uri getHeaderIconUri(){ //要上傳的圖片 Resources r = getApplicationContext().getResources(); return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + r.getResourcePackageName(com.dora.feed.R.drawable.app_logo) + "/" + r.getResourceTypeName(com.dora.feed.R.drawable.app_logo) + "/" + r.getResourceEntryName(com.dora.feed.R.drawable.app_logo)); }
經過數日的努力,新聞客戶端終於完成了,想用博客記錄一下開發過程中遇到的問題和解決方法,以免以後遇到同樣的問題罵自己記性差.項目的前期准備做項目前應該仔細的規劃一下功能需求
Matrix的數學原理在Android中,如果你用Matrix進行過圖像處理,那麼一定知道Matrix這個類。Android中的Matrix是一個3 x 3的矩陣,其內容
Android中的sdcard是一個外部存儲目錄,是一個應用程序的私有目錄,只有當前應用程序有權限訪問讀寫,其他應用無權限訪問。一般用來存放一些安全性不高,但比較大的數據
Android 中使用ExpandableListView 實現分組一個視圖顯示垂直滾動兩級列表中的條目。這不同於列表視圖,允許兩個層次,類似於QQ的好友分組