Android Facebook和Twitter登录和分享完整版
最近公司的软件需要改国际版,需要Facebook和Twitter的登录和分享。
本人先用Umeng的第三方社会化分享实现了该功能,但是后来一想问题来了,经过查证。Umeng只在中国和美国有服务器,那也就是说别的国家的人如果用该产品登录和分享可不就成了摆设,这下苦逼了,然后就又重新推倒重来,索性用官方的facebook和twitter来实现登录和分享。具体步骤:
第一,因为中国政府各种坑比墙国外的服务器,导致facebook和twitter访问不了,那第一步就需要FQ,顺便FQ看看苍老师什么的,,,,我在网上找到了一个比较好的FQ软件:蓝灯(Lantern)

进入该网站,本人下载了mac版本。顺便做下载了对应的android apk,用法很简单。安装上之后开启就行了,这样你就能访问苍老师,天海翼了
第二步:既然咱们成功FQ了,那就开始咱们的步伐:
Facebook登录和分享
咱们先进入facebook的官网
然后注册账号。我使用邮箱注册的,注册完成之后就可以创建项目了

因为我已经创建过,所以这块就各位自己操作就行,
然后咱们要做的就是看文档。
进入此网站就可以看到facebook其实写的已经很清楚了:https://developers.facebook.com/docs/facebook-login/android

咱们在Android studio(本人用Android studio来写的程序,如果不太熟Android studio的可以自行在网上查查具体用法)中具体要怎么操作呢,如下![]()
因为facebook官网下载的sdk后缀名是(.aar)的,不是咱们正常的jar包,所以我索性就在Android studio中找jar包,就是如上图所示。
然后只需要按照facebook文档中的步骤往下就可以了
-------------------------------------------------------------------facebook文档开始-----------------------------------------------------------
A. 下载 Facebook 应用
点击下方的按钮,下载 Facebook 应用。
B. 创建开发者帐户
如果没有 Facebook 开发者帐户,请点击下面的按钮创建。您可以通过 Facebook 开发者帐户使用开发者工具和创建 Facebook 应用。
C. 下载 Android SDK
下载最新的 Android 版 Facebook SDK。
D. 获得 Facebook 应用编号、添加 SDK、以及向资料页添加密钥散列
点击下方的按钮,按照快速入门操作,也可以按照新手入门中的步骤操作。
E. 为应用启用单点登录
为应用启用单点登录的方法是:在 Facebook 开发者网站的我的应用中选择您的应用,然后选择应用的设置,并将单点登录设置为是。
F. 将FacebookActivity添加到AndroidManifest.xml中。
| 1 | </activity> | 
2.添加 Facebook“登录”按钮
将 Facebook 登录添加到应用的最简单方法是从 SDK 添加LoginButton。这是Button的自定义视图实施。您可以在应用中使用该按钮实施 Facebook 登录。
 
您可以结合LoginButton使用 SDK 提供的以下类:
- LoginManager— 使用请求的读取或发布权限开始登录流程。
- CallbackManager— 用于将调用按指定路径发送回 Facebook SDK 及您注册的回调。您应从开始活动或onActivityResult片段调用它。
- AccessToken:— 使用该类图谱 API 请求。它会显示用户编号以及用户接受和拒绝的权限。
- Profile— 该类包含关于已登录用户的基本信息。
LoginButton是一个界面元素,其中包含LoginManager具备的功能。因此,当用户点击此按钮时,就会以LoginManager中设置的权限开始登录。按钮随登录状态变化,并根据用户的身份验证状态显示正确文本。
要添加 Facebook 登录按钮,请先将其添加到布局 XML 文件中,并使用完整的类名称com.facebook.widget.LoginButton:
| 1 2 | <com.facebook.login.widget.loginbutton android:id="@+id/login_button"android:layout_gravity="center_horizontal"android:layout_height="wrap_content"android:layout_marginbottom="30dp"android:layout_margintop="30dp"android:layout_width="wrap_content">        </com.facebook.login.widget.loginbutton> | 
然后在界面中设置按钮:将按钮添加到片段中,并更新活动以使用片段。
您可以自定义Login button的属性,并在onCreateView()方法中注册一个回调。
您可以自定义的属性包括LoginBehavior、DefaultAudience、ToolTipPopup.Style以及LoginButton的相关权限。例如:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | @OverridepublicView 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, newFacebookCallback<loginresult>() {        @Override        publicvoidonSuccess(LoginResult loginResult) {            // App code        }        @Override        publicvoidonCancel() {            // App code        }        @Override        publicvoidonError(FacebookException exception) {            // App code        }    });    }</loginresult> | 
如果您在片段中使用LoginButton,需要通过调用setFragment来设置按钮上的片段,如图所示。
之后您需要调用FacebookSdk.sdkInitialize来初始化 SDK,然后调用CallbackManager.Factory.create来创建回调管理器,以便处理登录响应。以下是在片段中添加回调的示例:
| 1 2 3 4 5 6 7 8 9 10 | publicclassMainActivity extendsFragmentActivity {    CallbackManager callbackManager;    @Override    publicvoidonCreate(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, newFacebookCallback<loginresult>() { ... });    }</loginresult> | 
最后您应调用callbackManager.onActivityResult,以便通过callbackManager将登录结果传递至LoginManager。
3.注册回调
为了响应登录结果,您需要使用LoginManager或LoginButton注册回调。如果您使用LoginButton注册回调,就不需要在登录管理器中注册回调。
将回调添加到活动或片段的onCreate()方法:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | @OverridepublicvoidonCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    FacebookSdk.sdkInitialize(this.getApplicationContext());    callbackManager = CallbackManager.Factory.create();    LoginManager.getInstance().registerCallback(callbackManager,            newFacebookCallback<loginresult>() {                @Override                publicvoidonSuccess(LoginResult loginResult) {                    // App code                }                @Override                publicvoidonCancel() {                     // App code                }                @Override                publicvoidonError(FacebookException exception) {                     // App code                   }    });}</loginresult> | 
如果登录成功,LoginResult参数将拥有新的AccessToken及最新授予或拒绝的权限。
您不需要registerCallback来保证登录成功,可以选择使用下述AccessTokenTracker类跟踪当前访问口令的更改。
之后在onActivityResult()中,将登录结果转发到在onCreate()中创建的callbackManager:
| 1 2 3 4 5 | @OverrideprotectedvoidonActivityResult(intrequestCode, intresultCode, Intent data) {    super.onActivityResult(requestCode, resultCode, data);    callbackManager.onActivityResult(requestCode, resultCode, data);} | 
您集成到 FacebookSDK 登录或分享的所有活动和片段都应将onActivityResult转发给 callbackManager
-------------------------------------------------------------------facebook文档结束------------------------------------------------
如上的步骤就可以了吗?答案是NO,原因是因为我们还没有配置SDK。那我们就接着配置Facebook的SDK呗。


然后一定需要配置SDK,一定要配置Key Hashes。否则当您授权时就会出现错误。
所提供的网址不被应用程序配置所接纳
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | FacebookSdk.sdkInitialize(getApplicationContext());        AppEventsLogger.activateApp(this);        TwitterAuthConfig authConfig = newTwitterAuthConfig(TWITTER_KEY, TWITTER_SECRET);        Fabric.with(this, newTwitter(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) {        } | 
然后我们就需要添加登录代码块了,如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | /**     * FaceBook登录     */    publicvoidLoginFaceBook(){        List<string> permissions = Arrays.asList("public_profile", "user_friends", "user_status");        LoginManager.getInstance().logInWithReadPermissions(activity, permissions);        LoginManager.getInstance().registerCallback(callbackManager, newFacebookCallback<loginresult>() {            @Override            publicvoidonSuccess(LoginResult loginResult) {                // App code                SysoutUtil.out("logingResult:"+ loginResult);                AccessToken accessToken = loginResult.getAccessToken();                GraphRequest request = GraphRequest.newMeRequest(accessToken, newGraphRequest.GraphJSONObjectCallback() {                   @Override                    publicvoidonCompleted(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 = newJSONObject(picture);                            String data = jsonObject.getString("data");                            imageUrl = newJSONObject(data).getString("url");                        } catch(JSONException e) {                            e.printStackTrace();                        }                     }                });                //包入你想要得到的資料 送出request                Bundle parameters = newBundle();                parameters.putString("fields", DEFAULT_REQUEST_VALUE);                request.setParameters(parameters);                request.executeAsync();            }            @Override            publicvoidonCancel() {                SysoutUtil.out("onCancel:");            }            @Override            publicvoidonError(FacebookException exception) {                // App code                SysoutUtil.out("onError:");            }        });    }</loginresult></string> | 
| 1 2 3 4 5 6 7 8 9 10 11 12 | @Override    protectedvoidonActivityResult(intrequestCode, intresultCode, 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);    } | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | /**     * 分享到facebook     */    privateCallbackManager callBackManager;    publicvoidshareFaceBook() {        Bitmap image = BitmapFactory.decodeResource(getResources(), com.dora.feed.R.drawable.app_logo);        callBackManager  = CallbackManager.Factory.create();        newFaceBookShareUtils(this,callBackManager,facebookCallback)                .share(getResources().getString(R.string.app_name),                        image,                        getResources().getString(R.string.share_tips_tips));    } | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | packagecom.dora.feed.utils;/** * Created by wangkai on 16/9/3. */importandroid.app.Activity;importandroid.graphics.Bitmap;importandroid.graphics.BitmapFactory;importandroid.net.Uri;importcom.dora.feed.net.Api;importcom.facebook.CallbackManager;importcom.facebook.FacebookCallback;importcom.facebook.share.ShareApi;importcom.facebook.share.model.ShareHashtag;importcom.facebook.share.model.ShareLinkContent;importcom.facebook.share.model.SharePhoto;importcom.facebook.share.model.SharePhotoContent;importcom.facebook.share.widget.ShareDialog;/** * facebook分享工具类 * Created by Song on 2016/7/5. * Email:songxueliang@huiqu.co */publicclassFaceBookShareUtils {    privateActivity mActivity ;    privateShareDialog shareDialog;    privateCallbackManager callBackManager;    publicstaticfinalintSHARE_REQUEST_CODE = 10010;    privateShareLinkContent.Builder shareLinkContentBuilder;    publicFaceBookShareUtils(Activity activity, CallbackManager callBackManager, FacebookCallback facebookCallback) {        this.mActivity = activity ;        this.callBackManager = callBackManager;        shareDialog = newShareDialog(mActivity);        //注册分享状态监听回调接口        shareDialog.registerCallback(callBackManager, facebookCallback, FaceBookShareUtils.SHARE_REQUEST_CODE);        shareLinkContentBuilder = newShareLinkContent.Builder();    }    /**     * 分享     */    publicvoidshare(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);        }    }    /**     * 分享     */    publicvoidshare(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 = newShareLinkContent.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))                    .build();            shareDialog.show(linkContent);        }    }} | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | /**     * facebook分享状态回调     */    privateFacebookCallback facebookCallback = newFacebookCallback() {        @Override        publicvoidonSuccess(Object o) {            SysoutUtil.out("onSuccess"+ o.toString());//            Message msg = Message.obtain();//            msg.what = SHARE_COMPLETE;//            mHandler.sendMessage(msg);        }        @Override        publicvoidonCancel() {            SysoutUtil.out("onCancel");//            Message msg = Message.obtain();//            msg.what = SHARE_CANCEL;//            mHandler.sendMessage(msg);        }        @Override        publicvoidonError(FacebookException error) {            SysoutUtil.out("onError");            ToastUtils.showToast("share error--"+ error.getMessage());//            Message msg = Message.obtain();//            msg.what = SHARE_ERROR;//            mHandler.sendMessage(msg);        }    }; | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @Override    protectedvoidonActivityResult(intrequestCode, intresultCode, Intent data) {        if(PromptUtils.isProgressDialogShowing()){            PromptUtils.dismissProgressDialog();        }        if(FaceBookShareUtils.SHARE_REQUEST_CODE == requestCode) {            callBackManager.onActivityResult(requestCode,resultCode,data);        }elseif(requestCode == TWEET_COMPOSER_REQUEST_CODE){            SysoutUtil.out("onActivityResult");            ToastUtils.showToast("share success");        }//        callBackManager.onActivityResult(requestCode,resultCode,data);    } | 
好了,按照以上步骤,您的facebook登录和分享就可以成功了,休息下咱们再开始写twitter的登录和注册。。。。。。。。。。。。。
Twitter登录和分享
Twitter本人研究了三天,看各种文档,twitter的源码,最后才实现了
首先还是看文档:
Twitter的文档很不好找,https://www.fabric.io/kits/android/twitterkit/install
在文档中可以很清楚的看到,应该如何配置Fabric
看我的代码具体实现:
首先配置项目的build.gradle(也就是最外边的一个gradle)
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // Top-level build file where you can add configuration options common to all sub-projects/modules.buildscript {    repositories {        jcenter()    }    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
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 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 {}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;    }} | 
下载完成之后咱们要做的就是开始写代码:
Twitter的初始化在前边的代码中已经有体现。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | /**     * Twitter登录     */    privatevoidLoginTwitter(){        loginButton.setCallback(newCallback<twittersession>() {            @Override            publicvoidsuccess(Result<twittersession> result) {                TwitterApiClient twitterApiClient = TwitterCore.getInstance().getApiClient();                Call<user> call =  twitterApiClient.getAccountService().verifyCredentials(false, false);                call.enqueue(newCallback<user>() {                    @Override                    publicvoidsuccess(Result<user> 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                    publicvoidfailure(TwitterException exception) {                        System.out.println(exception.getMessage());                    }                });            }            @Override            publicvoidfailure(TwitterException exception) {                SysoutUtil.out("TwitterKit"+ "Login with Twitter failure"+ exception);            }        });</user></user></user></twittersession></twittersession> | 
到此处登录就完成了,并且您的头像以及各种信息都能取到,本人逛了很多国外网站都说通过 接口的形式来重新获取用户信息,然后twitter官方也建议这么做,但是在我用的时候接口一直返回“215”,本人试了不下上百次,把该接口各种配置,但是怎么都返回215,215的大致意思是我需要重新验证身份,那我就想不通了,我再登录之前肯定验证身份了,不知道是为啥,最后我实在崩溃了;



我就想既然这种方法实现不了,那我就换种思路,程序员最重要的一点就是要能看代码,那我索性就看twitter jar包的源码了,果然看源码还是很有用的,最后发现twitter中的用户信息存储在User类下,然后我只需要获取到User的数据不就行了,然后就是一步一步的开始看源码,最后终于找到解决方案了如下图,

到此为止,我们的登录就算完整了,用户的所有信息想怎么取就怎么取。
最后我们在做分享
分享很简单,我就不做解释了,直接将本方法拷入代码,调用就可以:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | /**     * 分享到Twitter     * @throws MalformedURLException     */    privatevoidshareTweet() throwsMalformedURLException {//        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 = newTweetComposer.Builder(this)                    .text("标题")                      .url(newURL("您的URL"))                    .image(getHeaderIconUri())                    .createIntent();        } catch(MalformedURLException e) {            e.printStackTrace();        }        startActivityForResult(intent, TWEET_COMPOSER_REQUEST_CODE);    }    publicUri getHeaderIconUri(){   //要上传的图片        Resources r =  getApplicationContext().getResources();        returnUri.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));    } | 
终于搞定,根据以上方式,facebook登录,分享 twitter登录和分享完美实现。本人能力有限,写的比较粗糙,要是有问题请留言,本人再优化
 
                    
                     
                    
                 
                    
                
 
                
            
         
 
         浙公网安备 33010602011771号
浙公网安备 33010602011771号