Android 中 LinkedIn 的 Oauth 2.0 授权

2024-06-30

即使 linkedIn 没有这样的 Android 特定 sdk(例如适用于 android 的 facebook 和 twitter sdk)。使用 Oauth 1.0 设置 linkedIn 授权仍然很容易使用:

  • 抄写员java https://github.com/fernandezpablo85/scribe-java
  • 社交认证 https://code.google.com/p/socialauth-android/对于安卓。
  • 以及名单tools http://developer.linkedin.com/documents/libraries-and-tools here.

但 Oauth 2.0 授权的情况就不一样了。对于 Android 特定示例来说,没有太多有用的库。我尝试使用这些:

  • Android Oauth 客户端 https://github.com/wuman/android-oauth-client
  • tnj https://github.com/tnj/AndroidOAuthExample.

我了解到 Oauth 2.0 比 1.0 更容易实现。但我仍然无法这样做。

有没有关于在 Android 中为 LinkedIn 实施 Oauth2.0 的建议?


LinkedIN 的 Oauth2.0 身份验证。

Step 1:

  • 按照以下步骤向 linkedIn 注册您的应用程序这个文件。 https://developer.linkedin.com/documents/authentication并获取您的 api_key 和 api_secret。

Step 2:

主要活动:

public class MainActivity extends Activity {

/*CONSTANT FOR THE AUTHORIZATION PROCESS*/

/****FILL THIS WITH YOUR INFORMATION*********/
//This is the public api key of our application
private static final String API_KEY = "YOUR_API_KEY";
//This is the private api key of our application
private static final String SECRET_KEY = "YOUR_API_SECRET";
//This is any string we want to use. This will be used for avoiding CSRF attacks. You can generate one here: http://strongpasswordgenerator.com/
private static final String STATE = "E3ZYKC1T6H2yP4z";
//This is the url that LinkedIn Auth process will redirect to. We can put whatever we want that starts with http:// or https:// .
//We use a made up url that we will intercept when redirecting. Avoid Uppercases. 
private static final String REDIRECT_URI = "http://com.amalbit.redirecturl";
/*********************************************/

//These are constants used for build the urls
private static final String AUTHORIZATION_URL = "https://www.linkedin.com/uas/oauth2/authorization";
private static final String ACCESS_TOKEN_URL = "https://www.linkedin.com/uas/oauth2/accessToken";
private static final String SECRET_KEY_PARAM = "client_secret";
private static final String RESPONSE_TYPE_PARAM = "response_type";
private static final String GRANT_TYPE_PARAM = "grant_type";
private static final String GRANT_TYPE = "authorization_code";
private static final String RESPONSE_TYPE_VALUE ="code";
private static final String CLIENT_ID_PARAM = "client_id";
private static final String STATE_PARAM = "state";
private static final String REDIRECT_URI_PARAM = "redirect_uri";
/*---------------------------------------*/
private static final String QUESTION_MARK = "?";
private static final String AMPERSAND = "&";
private static final String EQUALS = "=";

private WebView webView;
private ProgressDialog pd;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //get the webView from the layout
    webView = (WebView) findViewById(R.id.main_activity_web_view);

    //Request focus for the webview
    webView.requestFocus(View.FOCUS_DOWN);

    //Show a progress dialog to the user
    pd = ProgressDialog.show(this, "", this.getString(R.string.loading),true);

    //Set a custom web view client
    webView.setWebViewClient(new WebViewClient(){
          @Override
          public void onPageFinished(WebView view, String url) {
                //This method will be executed each time a page finished loading.
                //The only we do is dismiss the progressDialog, in case we are showing any.
              if(pd!=null && pd.isShowing()){
                  pd.dismiss();
              }
          }
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String authorizationUrl) {
            //This method will be called when the Auth proccess redirect to our RedirectUri.
            //We will check the url looking for our RedirectUri.
            if(authorizationUrl.startsWith(REDIRECT_URI)){
                Log.i("Authorize", "");
                Uri uri = Uri.parse(authorizationUrl);
                //We take from the url the authorizationToken and the state token. We have to check that the state token returned by the Service is the same we sent.
                //If not, that means the request may be a result of CSRF and must be rejected.
                String stateToken = uri.getQueryParameter(STATE_PARAM);
                if(stateToken==null || !stateToken.equals(STATE)){
                    Log.e("Authorize", "State token doesn't match");
                    return true;
                }

                //If the user doesn't allow authorization to our application, the authorizationToken Will be null.
                String authorizationToken = uri.getQueryParameter(RESPONSE_TYPE_VALUE);
                if(authorizationToken==null){
                    Log.i("Authorize", "The user doesn't allow authorization.");
                    return true;
                }
                Log.i("Authorize", "Auth token received: "+authorizationToken);

                //Generate URL for requesting Access Token
                String accessTokenUrl = getAccessTokenUrl(authorizationToken);
                //We make the request in a AsyncTask
                new PostRequestAsyncTask().execute(accessTokenUrl);

            }else{
                //Default behaviour
                Log.i("Authorize","Redirecting to: "+authorizationUrl);
                webView.loadUrl(authorizationUrl);
            }
            return true;
        }
    });

    //Get the authorization Url
    String authUrl = getAuthorizationUrl();
    Log.i("Authorize","Loading Auth Url: "+authUrl);
    //Load the authorization URL into the webView
    webView.loadUrl(authUrl);
}

/**
 * Method that generates the url for get the access token from the Service
 * @return Url
 */
private static String getAccessTokenUrl(String authorizationToken){
    return ACCESS_TOKEN_URL
            +QUESTION_MARK
            +GRANT_TYPE_PARAM+EQUALS+GRANT_TYPE
            +AMPERSAND
            +RESPONSE_TYPE_VALUE+EQUALS+authorizationToken
            +AMPERSAND
            +CLIENT_ID_PARAM+EQUALS+API_KEY
            +AMPERSAND
            +REDIRECT_URI_PARAM+EQUALS+REDIRECT_URI
            +AMPERSAND
            +SECRET_KEY_PARAM+EQUALS+SECRET_KEY;
}
/**
 * Method that generates the url for get the authorization token from the Service
 * @return Url
 */
private static String getAuthorizationUrl(){
    return AUTHORIZATION_URL
            +QUESTION_MARK+RESPONSE_TYPE_PARAM+EQUALS+RESPONSE_TYPE_VALUE
            +AMPERSAND+CLIENT_ID_PARAM+EQUALS+API_KEY
            +AMPERSAND+STATE_PARAM+EQUALS+STATE
            +AMPERSAND+REDIRECT_URI_PARAM+EQUALS+REDIRECT_URI;
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

private class PostRequestAsyncTask extends AsyncTask<String, Void, Boolean>{

    @Override
    protected void onPreExecute(){
        pd = ProgressDialog.show(MainActivity.this, "", MainActivity.this.getString(R.string.loading),true);
    }

    @Override
    protected Boolean doInBackground(String... urls) {
        if(urls.length>0){
            String url = urls[0];
            HttpClient httpClient = new DefaultHttpClient();
            HttpPost httpost = new HttpPost(url);
            try{
                HttpResponse response = httpClient.execute(httpost);
                if(response!=null){
                    //If status is OK 200
                    if(response.getStatusLine().getStatusCode()==200){
                        String result = EntityUtils.toString(response.getEntity());
                        //Convert the string result to a JSON Object
                        JSONObject resultJson = new JSONObject(result);
                        //Extract data from JSON Response
                        int expiresIn = resultJson.has("expires_in") ? resultJson.getInt("expires_in") : 0;

                        String accessToken = resultJson.has("access_token") ? resultJson.getString("access_token") : null;
                        Log.e("Tokenm", ""+accessToken);
                        if(expiresIn>0 && accessToken!=null){
                            Log.i("Authorize", "This is the access Token: "+accessToken+". It will expires in "+expiresIn+" secs");

                            //Calculate date of expiration
                            Calendar calendar = Calendar.getInstance();
                            calendar.add(Calendar.SECOND, expiresIn);
                            long expireDate = calendar.getTimeInMillis();

                            ////Store both expires in and access token in shared preferences
                            SharedPreferences preferences = MainActivity.this.getSharedPreferences("user_info", 0);
                            SharedPreferences.Editor editor = preferences.edit();
                            editor.putLong("expires", expireDate);
                            editor.putString("accessToken", accessToken);
                            editor.commit();

                            return true;
                        }
                    }
                }
            }catch(IOException e){
                Log.e("Authorize","Error Http response "+e.getLocalizedMessage());  
            }
            catch (ParseException e) {
                Log.e("Authorize","Error Parsing Http response "+e.getLocalizedMessage());
            } catch (JSONException e) {
                Log.e("Authorize","Error Parsing Http response "+e.getLocalizedMessage());
            }
        }
        return false;
    }

    @Override
    protected void onPostExecute(Boolean status){
        if(pd!=null && pd.isShowing()){
            pd.dismiss();
        }
        if(status){
            //If everything went Ok, change to another activity.
            Intent startProfileActivity = new Intent(MainActivity.this, ProfileActivity.class);
            MainActivity.this.startActivity(startProfileActivity);
        }
    }

};
}

和 xmlLayout:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <WebView
        android:id="@+id/main_activity_web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

令牌保存在共享首选项文件中。

简单的 Android 项目仓库在github上 https://github.com/amalChandran/LinkedInAndroid20.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android 中 LinkedIn 的 Oauth 2.0 授权 的相关文章

  • Samsung Galaxy J1 4G 上的 webRTC 应用程序崩溃

    我正在开发视频通话 Android 应用程序 该应用程序可以在 Nexus 4 Moto g2 Moto g3 Moto e 等设备上进行视频通话 但当我在 Samsung Galaxy J1 4G 上拨打电话时 它崩溃了 这是堆栈跟踪 E
  • 在Retrofit 2.0中如何获取JSON对象而不进行转换?

    我需要从 REST 服务器下载 json 对象 而不用 GSON 进行转换 但不明白Retrofit 2 0 bata 1 中如何make 只需使用JsonElement作为你的pojo 例如 在您的 Flower Api 界面中 GET
  • Android SDK Lint 工具忽略 NewAPI 警告

    我正在从 Eclipse Android SDK 运行 Lint 工具 我的设置是默认设置 并且 NewApi 在我的 Android Lint 设置中设置为错误 然而 当我运行 Lint 时 通过Package Explorer gt A
  • 以编程方式切换进度条的颜色

    所以我有一个图层列表 其中包含一个具有形状和纯色的项目 现在我想在我的代码中更改这种颜色
  • 待定意图的多个实例

    我创建了一个小部件 单击该小部件会激活 PendingIntent 问题是 当我屏幕上有多个小部件时 只有最新的小部件才会启动 PendingIntent 我读过一些关于独特请求代码的内容 但没有弄清楚这一点 有什么想法可以让多个小部件和
  • 如何获取已发送短信的送达报告?

    In my Application我正在使用发送短信SMS Manager 要检查消息是否已发送 我正在使用Toast 代替Toast我想要得到SMS Delivery Report我正在尝试很多例子 但是 一个流程不显示递送报告 例如当我
  • 无法解析“:app@debug/compileClasspath”的依赖关系:无法解析

    新安装的安卓工作室3 1 3在创建新项目并第一次编译时出现奇怪的依赖关系错误 一个相似的question https stackoverflow com questions 46949622 android studio 3 0 unabl
  • Android模拟器相机自定义图像

    有谁知道模拟器相机启动时可以打开一些个人照片吗 我有一个基于图像分析的应用程序 我希望当我单击相机按钮时 相机会打开而不是默认的 Android 模拟器移动图像 我希望它打开一些我设置为默认图像的图像 因此 当我选择拍照时 它只会显示该图像
  • 使用硬件键盘时 Android TabHost 选项卡会窃取焦点

    我目前有一个TabHost包含 4 个选项卡 在一些片段上我们有一些EditText布局内的视图 我们注意到 当您尝试输入任何内容时EditText使用硬件键盘的视图 焦点被窃取EditText并赋予当前活动选项卡TabHost 这只发生在
  • 关于ListView中ViewHolder模式实现优化

    因此 众所周知的 ViewHolder 模式通常看起来像 ListAdapter Override public View getView final int position View convertView final ViewGrou
  • Kotlin 协程的现有 3 函数回调

    我有一个带有具体示例的一般性问题 我想在拍照时使用 Kotlin 协程魔法而不是 Android 中的回调地狱 manager openCamera cameraId object CameraDevice StateCallback ov
  • 从 Android 上的 .net Web 服务获取列表

    我有 net Web 服务 我想在 android 上使用它 这个网络服务的方法返回List Of String 但我在android上没有得到响应 我能做些什么 这是代码 我已经研究了 3 天 但还没有找到任何解决方案 简而言之 我需要来
  • 如何以编程方式显示/隐藏导航抽屉

    我如何使用按钮来显示 隐藏导航抽屉 我已经使用过this https stackoverflow com questions 20971245 navigation drawer without actionbar 20971952 209
  • 是否可以从 Linux CLI 编译适用于 Android 的 Xamarin?

    我们有一个 Android 应用程序 它根据每个客户端使用自定义信息进行编译 目前 我们的应用程序是使用 Ionic 构建的 因此当用户要求下载 APK 时 我们会自动相应地修改其源代码 编译应用程序并提供从客户端的下载 所有这一切都是在
  • 将 Android SDK 工具更新至修订版 14 后出现 Ant 问题

    安装 Android SDK 工具修订版 14 执行 ant version 时为 ant 版本 1 8 2 以在 Android 4 0 ICS 上安装和测试我们的应用程序后 我注意到我们的自动构建脚本现在失败了 构建脚本正在执行 ant
  • Android Studio 3.1 中任务“:app:transformClassesWithAndroidGradleClassShrinkerForDebug”执行失败

    我刚刚从 Android Studio 升级3 1到 Android Studio3 1 1 但仍然使用 Gradle 构建工具3 0 0 当我运行我的应用程序时 它会导致此错误 app transformClassesWithAndroi
  • UserRecoverableAuthException:NeedPermission

    我尝试按照教程进行操作 https developers google com android guides http auth https developers google com android guides http auth Co
  • 从相同的代码创建应用程序的免费/付费版本

    所以我现在要讨论我的应用程序的发布时间了 我们计划发布两个版本 一个是基于广告的免费解锁版本 另一个是付费完全解锁版本 我设置了代码 只需在启动时设置一个标志即可启用 禁用广告并锁定 解锁所有功能 因此 从字面上看 这些版本之间只有一行代码
  • 无法解析目标“android-16”

    我使用的是安卓4 2 2 安装最新的SDK后 当我打开eclipse时 我可以看到所有在构建过程中出现问题的项目 以下是我得到的错误 请让我知道如何解决这个问题 Unable to resolve target android 16 我也遇
  • EditText“maxLines”属性不起作用

    我有一个多行 EditText 用户可以在其中输入长句子 这就是我想要的 高度为 6 行的 EditText 从第一行到第五行 我希望 EditText 的 IME 操作按钮具有 Enter 转到新行 按钮 在第六 最后 行 它应该更改为

随机推荐

  • Karma 无法使用 Jenkins 和 Ubuntu 12.04 启动 Firefox

    我已经设置了一个应该运行 Firefox 的 Jenkins 作业 使用 Jenkins 用户登录 Ubuntu 我可以毫无问题地手动启动 Firefox 然而 当我在詹金斯运行这项工作时 我得到 EnvInject Loading nod
  • 在 *ngFor 中创建局部变量

    是否可以在 ngFor 中创建局部变量 例如 div 您可以将 ng container 与 ngIf 结合使用来实现此目的 div class message list div div
  • 带有预先计算值的 geom_boxplot

    过去 我已经能够使用 ggplot2 创建箱线图 方法是提供下须线 下分位数 中位数 上分位数和上须线以及 x 轴标签 例如 DF lt data frame x c A B min c 1 2 low c 2 3 mid c 3 4 to
  • 如何检查 iPhone 的 IPv6 地址

    我已经根据苹果的建议设置了 IPv6 nat64 环境 https developer apple com library ios documentation NetworkingInternetWeb Conceptual Network
  • 如何将根域和子域都指向Google Cloud Storage存储桶?

    我已经成功创建了一个托管在 Google Cloud Storage 上的静态网站 存储桶名称类似于 www example com 我的 www 的 CNAME 记录指向c storage googleapis com 我已使用 Goog
  • 从线程队列中获取所有项目

    我有一个线程将结果写入队列 在另一个线程 GUI 中 我定期 在 IDLE 事件中 检查队列中是否有结果 如下所示 def queue get all q items while 1 try items append q get nowai
  • MySQL 将 COMMENT 添加到外键

    我正在将旧数据库 SyBase 转换为 MySQL 并且有以下 DDL 查询 ALTER TABLE DBA tab prodotto ADD FOREIGN KEY fkey idlinea tpr idlin REFERENCES DB
  • 样式选项标签[重复]

    这个问题在这里已经有答案了 我有一个包含选项的下拉菜单 我想部分地打破和粗体一些文本以及插入上下文中断 我尝试使用 CSS 和 HTML 标签 但无法得到它 有人可以建议一个解决方案吗 提前致谢 我知道这个问题有点老了 或者至少不是新的 但
  • Codeigniter 错误:不允许您尝试上传的文件类型

    如果我上传一个csv文件 没有问题localhost一切工作正常 但是当我在实时服务器上上传我的应用程序并上传csv文件然后抛出此错误 The filetype you are attempting to upload is not all
  • 从网页获取 chrome.storage.sync.get

    大家好 我希望能够从网页内的内联脚本访问 chrome storage sync 中存储的信息 由我的扩展程序注入 当尝试使用 chrome storage sync 时 无法从 未定义 调用同步 同样 我无法调用 chrome runti
  • 在 Silverlight 中调用 WCF 服务时使用 Observable.FromEvent

    我正在尝试使用 NET Reactive Framework 来简化对我正在编写的 Silverlight 3 应用程序使用的 WCF 服务的一些异步调用 问题是我很难找到一种有效的方式来构建我的代码 毫无疑问 部分问题是了解 Reacti
  • 如何安装“Android 支持库”以将 Gluon Mobile 应用程序部署到 Android?

    我想使用 Gluon Mobile 框架开发一个 Android 应用程序 我在 Netbeans IDE 中安装了 Gluon 插件 创建了一个示例项目并成功构建了它 现在我想将该应用程序部署到 Android 设备 我指的是在线文档 1
  • Chrome 开发工具准确计算 CSS 规则值

    无论如何 例如我可以获取要在 Chrome 开发工具中显示的字体的确切像素值 带小数位 吗 In Firebug 如下 当我定义 value 它显示精确的计算值 以像素为单位 最多 4 位小数 In Chrome 开发工具 如下 它仅显示整
  • 我不明白这个霍夫曼算法的实现

    template
  • 数据更改后 ListView 未更新

    我正在使用两个ListViews List1 有数据 List2 为空 用户可以输入名称作为输入 如果 List1 包含名称 则添加Button按下后 标记应减 1 并且ListViews应该更新 Example 如果 List1 有 10
  • 以编程方式创建图像的缩略图

    在我的应用程序中 我从服务器获取图像 并且能够在图像视图中显示图像 但现在我想将从服务器获取的图像存储在表视图中 并在单击表视图单元格时显示它们 我想要的是如何制作图像的缩略图 以便将其显示在表视图单元格中 如果我直接在表视图单元格中显示图
  • 为什么 RDP 与其他远程控制软件相比如此快?

    我使用基于 RDP 的 Windows 远程客户端桌面实用程序从笔记本电脑连接到桌面 它比 TeamViewer 等远程控制应用程序更快 更美观 出于好奇 为什么 RDP 更好 谢谢 RDP 是一种允许传输低级屏幕绘制操作的特定协议 它还知
  • ViewCompat.setOnApplyWindowInsetsListener使状态栏颜色消失

    这是我用来检测何时的代码Keyboard Height变化 唯一的问题是Statur Bar当此代码运行时 颜色消失并变为白色 ViewCompat setOnApplyWindowInsetsListener this getWindow
  • 带有 Segoe UI 和日语文本的组合框

    我目前正在尝试让我的 C 应用程序在 Windows Vista 或 Windows 7 中运行时看起来更好 默认情况下 Windows 窗体应用程序使用微软无衬线字体字体 无法正确链接到亚洲清晰字体 例如Meiryo 为了解决这个问题 我
  • Android 中 LinkedIn 的 Oauth 2.0 授权

    即使 linkedIn 没有这样的 Android 特定 sdk 例如适用于 android 的 facebook 和 twitter sdk 使用 Oauth 1 0 设置 linkedIn 授权仍然很容易使用 抄写员java https