├── .gitignore ├── CHANGELOG.md ├── README.md ├── sample ├── .gitignore ├── app │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── xiaomi │ │ │ └── account │ │ │ └── openauth │ │ │ └── demo │ │ │ └── ui │ │ │ ├── CustomizedAuthorizedActivity.java │ │ │ └── MainActivity.java │ │ └── res │ │ ├── drawable-hdpi │ │ └── ic_launcher.png │ │ ├── drawable-mdpi │ │ └── ic_launcher.png │ │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ │ ├── drawable-xxhdpi │ │ └── ic_launcher.png │ │ ├── layout │ │ ├── activity_main.xml │ │ └── activity_main_old.xml │ │ ├── menu │ │ └── main.xml │ │ ├── values-sw600dp │ │ └── dimens.xml │ │ ├── values-sw720dp-land │ │ └── dimens.xml │ │ ├── values-v11 │ │ └── styles.xml │ │ ├── values-v14 │ │ └── styles.xml │ │ └── values │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle └── sdk ├── README.md ├── oauth.1.0.jar ├── oauth.1.1.jar ├── oauth.1.2.jar ├── oauth.1.3.jar ├── oauth.1.4.1.jar ├── oauth.1.4.2.jar ├── oauth.1.4.jar ├── oauth.1.5.1.jar ├── oauth.1.5.2.jar ├── oauth.1.5.jar ├── oauth.1.6.4.jar ├── oauth.1.6.5.jar ├── xiaomi-oauth.1.6.6.jar ├── xiaomi-oauth.1.6.7.jar └── xiaomi-oauth.1.6.8.jar /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 1.7.1 2 | - 修复fastOAuth总是返回code, 即使使用accessToken 3 | 4 | # 1.7.0 5 | - 修复在三星手机上有时无法打开米家 6 | 7 | # 1.6.9 8 | - 支持通过米家进行oauth授权 9 | - 支持手机号自动填充 10 | - 支持通过gradle方式依赖 11 | 12 | # 1.6.8 13 | - 修复4.3上出现白屏的问题 14 | 15 | # 1.6.6 16 | - 支持通过miui9.5之后的系统帐号授权 17 | 18 | # 1.6.4 19 | - 支持小爱音箱水滴平台 20 | 21 | # 1.5.1 22 | - fix bugs 23 | 24 | # 1.5 25 | - fix Activity resource leak 26 | - add fastOAuth 27 | 28 | # 1.4.2 29 | - fix bug that AuthorizeActivity may crash if the deprecated "static" version of XiaomiOAuthorize#startGetAccessToken()/startGetOAuth() are called. This bug is instroduced in 1.2 version. 30 | 31 | # 1.4.1 32 | - fix vulnerability that AuthorizeActivity can be DDOS-attacked by passing unrecognized Serializable in Intent's extra. 33 | 34 | # 1.4 35 | - fix vulnerability that AuthorizeActivity can be DDOS-attacked by passing unrecognized Parceable in Intent's extra. 36 | 37 | # 1.3 38 | - fix bug that AuthorizeActivity crashes on MIUI V6.4 and above version, which is intruduced in 1.2 version. 39 | 40 | # 1.2 41 | - fix bug that oauth may fail if redirectUrl has upper-case letters, which is introduced in 1.1. 42 | - fix bug that NoTitleBar-themed AuthorizeActivity may crash if network error is met, which is introduced in 1.1. 43 | - add XiaomiOAuthorize#setCustomizedAuthorizeActivityClass. 44 | 45 | # 1.1 46 | - fix bug that can't register Mi Account by Gmail in OAuth webview. 47 | - add progress bar in OAuth webview Activity. 48 | - add refresh button in OAuth webview Activity. 49 | 50 | # 1.0 51 | Init version 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 快速开始 2 | === 3 | 4 | # 此README已不再更新,点击[查看最新文档](https://mzd5tljlyv.feishu.cn/docs/doccnCKqdBhEUX5Lq5izm4Apswe#IQr3Hr) 5 | === 6 | 7 | ## 1) 预备步骤 8 | 在[小米开放平台](https://dev.mi.com/console/doc/detail?pId=897) 中创建应用,查看更多文档。 9 | 10 | 有如何关于接入 Android oauth sdk 的问题或建议,可以在[issus](https://github.com/xiaomi-passport/oauth-android-sdk/issues)中提出。 11 | 12 | ## 2) 在应用的里添加以下配置: 13 | 14 | 添加依赖, 总是依赖最新版本 或者 [查看release版本](https://github.com/xiaomi-passport/oauth-android-sdk/releases) 15 | 16 | ```groovy 17 | repositories { 18 | 19 | // maven { url 'https://raw.githubusercontent.com/xiaomi-passport/maven-repository/master/releases' } 20 | // github如果被X,需要换成下面这一行 21 | maven { url 'https://gitlab.com/xiaomi-passport/maven-repository/raw/master/releases' } 22 | } 23 | 24 | dependencies { 25 | compile 'com.xiaomi.account:oauth-android:latest.release' // 总是依赖最新版本 26 | } 27 | ``` 28 | ### 注意: 29 | 30 | 'com.xiaomi.account:oauth-android:3.1.1' 版本迁移至 https://packages.aliyun.com/repos/2028284-release-awMPKn/packages 31 | 若使用需要进行如下配置: 32 | 33 | (a) 在build.gradle中设置仓库的访问凭证 34 | ``` java 35 | allprojects { 36 | repositories { 37 | maven { 38 | url 'https://maven.aliyun.com/repository/public' 39 | } 40 | maven { 41 | credentials { 42 | username '************************' 43 | password '************' 44 | } 45 | url 'https://packages.aliyun.com/maven/repository/2028284-release-awMPKn/' 46 | } 47 | maven { 48 | credentials { 49 | username '************************' 50 | password '************' 51 | } 52 | url 'https://packages.aliyun.com/maven/repository/2028284-snapshot-gw4bH1/' 53 | } 54 | } 55 | } 56 | 57 | ``` 58 | 59 | (b)配置包信息,在你的build.gradle文件中加入你要引用的文件信息。 60 | ```java 61 | dependencies { 62 | compile 'com.xiaomi.account:oauth-android:3.1.1' 63 | } 64 | ``` 65 | 66 | AndroidManifest.xml 67 | ``` xml 68 | 69 | 70 | 71 | ``` 72 | 73 | ## 3) 授权并获取AccessToken/code 74 | 75 | ### 3.1 授权 76 | sdk会自行判断:在miui上,启动系统帐号进行授权;非miui上,使用webview登录然后授权 77 | 78 | ``` java 79 | XiaomiOAuthFuture future = new XiaomiOAuthorize() 80 | //开发者预先申请好的 AppID 81 | .setAppId(appID) 82 | // 开发者预先申请时填好的 redirectUrl 83 | // .setUseSystemAccountLogin(false) // 默认是true,,如果小米系统账号没有登录,则调起系统登录ui进行登录;如果设置为false ,如果小米系统账号没有登录,则返回错误吗code=-1004 代表系统账号未登录. 84 | .setRedirectUrl(redirectUri) 85 | // 设置登录方式,例如"qr"为扫码登录 86 | .setLoginType("qr") 87 | // (3.1.1版本支持)业务使用了帐号的sdk可以在h5页面定制ui, 值是业务提供的 88 | .setBannerBiz("test") 89 | // (3.1.1版本支持)隐藏二维码登录中下方的3个app图标 90 | .setHideQrApps(true) 91 | // 如果是要获得Code的方式,则把startGetAccessToken改成startGetOAuthCode即可。其他相同 92 | .startGetAccessToken(activity); 93 | 94 | ``` 95 | 96 | 获取授权结果AccessToken/code (在后台线程调用) 97 | 98 | ``` java 99 | // 接下来这一段必须在后台线程调用 100 | try { 101 | XiaomiOAuthResults result = future.getResult(); 102 | 103 | if (results.hasError()) { 104 | int errorCode = results.getErrorCode(); 105 | String errorMessage = results.getErrorMessage(); 106 | } else { 107 | String accessToken = results.getAccessToken(); 108 | String macKey = results.getMacKey(); 109 | String macAlgorithm = results.getMacAlgorithm(); 110 | } 111 | } catch (IOException e1) { 112 | // error 113 | } catch (OperationCanceledException e1) { 114 | // 用户取消 115 | } catch (XMAuthericationException e1) { 116 | // error 117 | } 118 | ``` 119 | 120 | ### 3.2 设置 scope (可选) 121 | 设置授权的权限列表,不设置默认是全部权限。 122 | 123 | ``` java 124 | XiaomiOAuthFuture future = new XiaomiOAuthorize() 125 | // ... 126 | // int数组,可以用XiaomiOAuthConstants.SCOPE_*等常量, 也可自己添加 127 | .setScope(scope) 128 | // ... 129 | ``` 130 | 131 | 简单来说,Scope代表了一个AccessToken的权限。当使用一个AccessToken去访问OpenApi时, 132 | 只有该AccessToken的Scope和该OpenApi需要的权限对得上的时候,服务器才会返回正确的结果,否则会报错。 133 | 代码中只有一个地方要用到Scope,那就是去拿AccessToken的时候。 134 | 135 | 代码中Scope的值应该是多少?请参照 dev.mi.com/console/doc/detail?pId=762, 136 | 然后根据APP需要访问到的API去决定用哪些scope。比如,我将用AccessToken去获取用户的个人资料和好友信息, 137 | 那么我的scope就应该是1和3。也可以用SDK中预定义好的常量XiaomiOAuthConstants.SCOPE_*** 138 | 139 | ### 3.3 使用webview登录授权时,自定义页面的activity (可选) 140 | 可以自定义设置actionbar、进度条等,可参照demo中的CustomizedAuthorizedActivity。 141 | 142 | ``` java 143 | XiaomiOAuthFuture future = new XiaomiOAuthorize() 144 | // ... 145 | // 设置自定义的非miui上登录界面(默认是AuthorizeActivity) 146 | .setCustomizedAuthorizeActivityClass(CustomizedAuthorizedActivity.class) 147 | // ... 148 | ``` 149 | 150 | ### 3.4 当用户已经授权过,不会再让用户确认 (可选) 151 | 当用户已经授权过,不会再让用户确认,用户此时无法切换帐号。 152 | 如果用户没有授权过,会再次弹起授权页面 153 | 154 | ``` java 155 | XiaomiOAuthFuture future = new XiaomiOAuthorize() 156 | // ... 157 | .setSkipConfirm(true) 158 | // ... 159 | ``` 160 | 161 | ### 3.5 在miui上以对话框方式授权 (可选) 162 | 效果:sdk检测miui上用户已经登录系统帐号时,弹出对话框 163 | 164 | + miui版本支持: 8.2以上。 8.2以下/非miui上 future.getResult()时抛出XMAuthericationException 165 | + 需已经登录系统账号,否则授权结果xiaomiOAuthResults.getErrorCode()返回错误码 XiaomiOAuthConstants.ERROR_LOGIN_FAILED(-1002) 166 | 167 | ``` java 168 | XiaomiOAuthFuture future = new XiaomiOAuthorize() 169 | // ... 170 | .fastOAuth(MainActivity.this, XiaomiOAuthorize.TYPE_TOKEN); 171 | 172 | ``` 173 | 174 | ### 3.6 使用高安全级别(系统浏览器登录) 175 | 176 | ``` java 177 | XiaomiOAuthFuture future = new XiaomiOAuthorize() 178 | // ... 179 | .setUseSystemBrowserLogin(true); 180 | 181 | ``` 182 | 183 | ## 4) 使用AccessToken获取用户信息 184 | 185 | 获取用户名片 186 | 187 | ``` java 188 | // 这一句可以在UI线程调用 189 | XiaomiOAuthFuture future = new XiaomiOAuthorize().callOpenApi(context, 190 | appId, 191 | XiaomiOAuthConstants.OPEN_API_PATH_PROFILE, 192 | results.getAccessToken(), 193 | results.getMacKey(), 194 | results.getMacAlgorithm()); 195 | ``` 196 | 197 | ``` java 198 | // 接下来这一段必须在后台线程调用 199 | try { 200 | String result = future.getResult(); 201 | } catch (IOException e1) { 202 | // error 203 | } catch (OperationCanceledException e1) { 204 | // error 205 | } catch (XMAuthericationException e1) { 206 | // error 207 | } 208 | ``` 209 | 210 | 更多接口请在 https://dev.mi.com/console/doc/detail?pId=713 查看 211 | 212 | 213 | ## 5) 更多OAuth资料? 214 | 215 | https://dev.mi.com/console/doc/detail?pId=897 216 | 217 | ## 6) 业务方接入log文档 218 | ``` java 219 | //app初始化 220 | public class DiagnosisDemoApplication extends Application { 221 | @Override 222 | public void onCreate() { 223 | super.onCreate(); 224 | // 初始化并设置日志类型 225 | DiagnosisController.init(this, "oauth"); 226 | } 227 | } 228 | 229 | 上层app打开诊断开关和信息页面 230 | 231 | import com.xiaomi.accountsdk.diagnosis.ui.PassportDiagnosisActivity; 232 | 233 | PassportDiagnosisActivity.start(MainActivity.this); 234 | 235 | ``` 236 | --------------- 237 | 238 | # Oauth-Android-sdk 239 | ## Quick Start 240 | 241 | ### 1. Preliminary steps 242 | 243 | To create an account for your app on http://dev.xiaomi.com 244 | 245 | + Go to the website and log in 246 | + Click on “管理控制台/Administrative Console” 247 | + Click on “手机及平板应用/Mobile and Tablets Apps” 248 | + Click on “创建应用/Create an app” 249 | + Fill in the app name and package name 250 | + Click on “创建/Create” 251 | + Write down the AppID shows up 252 | + Look for “账号接入服务/Account Access Services” 253 | + Click on “Details” 254 | + Click on “Enable now” 255 | + Fill in “授权回调地址/Authorized Redirect URL” 256 | + Click on “启用/Enable” 257 | + Enable needed Open API 258 | 259 | ### 2. Integrating the following code in “AndroidManifest.xml” 260 | ``` xml 261 | 262 | 263 | 264 | ``` 265 | 266 | ### 3. Authorizing and getting AccessToken/code 267 | 268 | + sdk is able to detect: if it’s on miui, taking system account to authorize; if it’s on other OEMs, taking webview to log in and then authorize 269 | + setCustomizedAuthorizeActivityClass(): it’s able to customize login page UI on non-miui roms, like actionbar, loading bar etc., please refer to CustomizedAuthorizedActivity in the demo. 270 | 271 | ``` java 272 | XiaomiOAuthFuture future = new XiaomiOAuthorize() 273 | //The AppID you got from xiaomi.com 274 | .setAppId(appID) 275 | // The redirectUrl you filled in in application 276 | .setRedirectUrl(redirectUri) 277 | // int array, you can use constant like XiaomiOAuthConstants.SCOPE_* 278 | .setScope(scope) 279 | // set login page for non-miui roms(AuthorizeActivity is default) 280 | .setCustomizedAuthorizeActivityClass(CustomizedAuthorizedActivity.class) 281 | // If you want Code instead of AccessToken,please replace startGetAccessToken with startGetOAuthCode 282 | .startGetAccessToken(activity); 283 | ``` 284 | 285 | #### fastOAuth – authorize on pop-up window on miui 286 | 287 | Effect: if sdk detect user has signed in with system account, the window will pop up 288 | 289 | + Support: miui v8.2+. On miui older than v8.2 and non-miui roms, future.getResult() will throw XMAuthericationException 290 | + System account/Mi account has to be logged in, otherwise future.getResult() will throw XMAuthericationException 291 | 292 | ``` java 293 | XiaomiOAuthFuture future = new XiaomiOAuthorize() 294 | .setAppId(getAppId()) 295 | .setRedirectUrl(getRedirectUri()) 296 | .setScope(getScopeFromUi()) 297 | .fastOAuth(MainActivity.this, XiaomiOAuthorize.TYPE_TOKEN); 298 | ``` 299 | 300 | + Getting authorized AccessToken/Code (call on a background thread) 301 | 302 | ``` java 303 | // Must call on the background thread 304 | try { 305 | XiaomiOAuthResults result = future.getResult(); 306 | 307 | if (results.hasError()) { 308 | int errorCode = results.getErrorCode(); 309 | String errorMessage = results.getErrorMessage(); 310 | } else { 311 | String accessToken = results.getAccessToken(); 312 | String macKey = results.getMacKey(); 313 | String macAlgorithm = results.getMacAlgorithm(); 314 | } 315 | } catch (IOException e1) { 316 | // error 317 | } catch (OperationCanceledException e1) { 318 | // User cancel 319 | } catch (XMAuthericationException e1) { 320 | // error 321 | } 322 | ``` 323 | 324 | ### 4. Getting user info with AccessToken 325 | 326 | Getting user card 327 | 328 | ``` java 329 | // Could call on the UI thread 330 | XiaomiOAuthFuture future = new XiaomiOAuthorize().callOpenApi(context, 331 | appId, 332 | XiaomiOAuthConstants.OPEN_API_PATH_PROFILE, 333 | results.getAccessToken(), 334 | results.getMacKey(), 335 | results.getMacAlgorithm()); 336 | 337 | 338 | //Must call on the background thread 339 | try { 340 | String result = future.getResult(); 341 | } catch (IOException e1) { 342 | // error 343 | } catch (OperationCanceledException e1) { 344 | // error 345 | } catch (XMAuthericationException e1) { 346 | // error 347 | } 348 | ``` 349 | 350 | ## Tips 351 | 352 | ### 1. SkipConfirm 353 | 354 | + When user has already authorized, will not ask again for authorization 355 | + It will be impossible for user to change an account 356 | + The process of popping up authorizing page will be slow 357 | 358 | ``` java 359 | XiaomiOAuthFuture future = new XiaomiOAuthorize() 360 | .setSkipConfirm(true) 361 | // .setOtherParams... 362 | // .startGetAccessToken(activity); 363 | ``` 364 | 365 | ### 2. Scope 366 | 367 | In simple terms, Scope is representing a permission of AccessToken. When using an ssAccessToken to access OpenApi, only if the Scope of the AccessToken is the permission that this OpenApi needed, the server will return a correct result, otherwise will produce an error. Scope will be used only once when getting the AccessToken. 368 | For the value of Scope, please refer to https://dev.mi.com/docs/passport/en/scopes/ , and please choose the scope based on the API you needed. For example, if getting user’s personal data and friends’ list on Mi Talk, then value of scope would be 1 and 2. Another defined constant in SDK XiaomiOAuthConstants.SCOPE_*** works as well, as long as relevant permissions were enabled on dev.xiaomi.com in preliminary steps. 369 | 370 | #### Please visit https://dev.mi.com/docs/passport/en/user-guide/ for more details 371 | -------------------------------------------------------------------------------- /sample/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /sample/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /sample/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | buildToolsVersion "26.0.2" 6 | 7 | defaultConfig { 8 | applicationId "com.xiaomi.account.oauthdemo" 9 | minSdkVersion 14 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | 23 | dependencies { 24 | // compile fileTree(dir: '../../sdk', include: ['xiaomi-oauth.1.6.8.jar']) 25 | compile 'com.xiaomi.account:oauth-android:latest.release' 26 | // compile project(":library") 27 | // compile 'com.xiaomi.account:phoneNumKeep:0.4.4' 28 | compile 'com.android.support:appcompat-v7:26.1.0' 29 | 30 | testCompile 'junit:junit:4.12' 31 | } 32 | -------------------------------------------------------------------------------- /sample/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/qidu/Android/Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /sample/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 23 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /sample/app/src/main/java/com/xiaomi/account/openauth/demo/ui/CustomizedAuthorizedActivity.java: -------------------------------------------------------------------------------- 1 | package com.xiaomi.account.openauth.demo.ui; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | import android.webkit.WebView; 6 | import android.widget.Button; 7 | import android.widget.LinearLayout; 8 | import android.widget.LinearLayout.LayoutParams; 9 | import android.widget.ProgressBar; 10 | 11 | import com.xiaomi.account.openauth.AuthorizeActivityBase; 12 | 13 | public class CustomizedAuthorizedActivity extends AuthorizeActivityBase{ 14 | 15 | private ProgressBar mProgressBar; 16 | private Button mRefreshButton; 17 | 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | 22 | LinearLayout layout = new LinearLayout(this); 23 | layout.setOrientation(LinearLayout.VERTICAL); 24 | layout.setLayoutParams(new LayoutParams( 25 | LayoutParams.MATCH_PARENT, 26 | LayoutParams.MATCH_PARENT)); 27 | 28 | mProgressBar = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal); 29 | layout.addView(mProgressBar, new LayoutParams( 30 | LayoutParams.MATCH_PARENT, 31 | LayoutParams.WRAP_CONTENT)); 32 | 33 | mRefreshButton = new Button(this); 34 | mRefreshButton.setText("click to refresh"); 35 | mRefreshButton.setOnClickListener(new View.OnClickListener() { 36 | @Override 37 | public void onClick(View v) { 38 | CustomizedAuthorizedActivity.this.refreshWebView(); 39 | } 40 | }); 41 | layout.addView(mRefreshButton); 42 | 43 | final WebView mWebView = super.getWebView(); 44 | layout.addView(mWebView, new LayoutParams( 45 | LayoutParams.MATCH_PARENT, 46 | LayoutParams.MATCH_PARENT)); 47 | 48 | setContentView(layout); 49 | } 50 | 51 | @Override 52 | protected void onShowProgress() { 53 | mProgressBar.setVisibility(View.VISIBLE); 54 | } 55 | 56 | @Override 57 | protected void onUpdateProgress(int newProgress) { 58 | mProgressBar.setProgress(newProgress); 59 | } 60 | 61 | @Override 62 | protected void onHideProgress() { 63 | mProgressBar.setVisibility(View.GONE); 64 | } 65 | 66 | @Override 67 | protected void onShowErrorUI() { 68 | mRefreshButton.setVisibility(View.VISIBLE); 69 | } 70 | 71 | @Override 72 | protected void onHideErrorUI() { 73 | mRefreshButton.setVisibility(View.GONE); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /sample/app/src/main/java/com/xiaomi/account/openauth/demo/ui/MainActivity.java: -------------------------------------------------------------------------------- 1 | 2 | package com.xiaomi.account.openauth.demo.ui; 3 | 4 | import android.Manifest; 5 | import android.accounts.OperationCanceledException; 6 | import android.annotation.SuppressLint; 7 | import android.app.Activity; 8 | import android.content.Intent; 9 | import android.os.AsyncTask; 10 | import android.os.Bundle; 11 | import android.support.v4.app.ActivityCompat; 12 | import android.support.v4.content.PermissionChecker; 13 | import android.util.Log; 14 | import android.view.Menu; 15 | import android.view.MenuItem; 16 | import android.view.View; 17 | import android.view.View.OnClickListener; 18 | import android.widget.CheckBox; 19 | import android.widget.EditText; 20 | import android.widget.TextView; 21 | import android.widget.Toast; 22 | 23 | import com.xiaomi.account.openauth.XMAuthericationException; 24 | import com.xiaomi.account.openauth.XiaomiOAuthConstants; 25 | import com.xiaomi.account.openauth.XiaomiOAuthFuture; 26 | import com.xiaomi.account.openauth.XiaomiOAuthResults; 27 | import com.xiaomi.account.openauth.XiaomiOAuthorize; 28 | import com.xiaomi.account.openauth.demo.R; 29 | 30 | import java.io.IOException; 31 | import java.text.SimpleDateFormat; 32 | import java.util.Arrays; 33 | import java.util.Date; 34 | import java.util.HashMap; 35 | import java.util.concurrent.Executor; 36 | import java.util.concurrent.Executors; 37 | 38 | import static android.content.pm.PackageManager.PERMISSION_DENIED; 39 | 40 | public class MainActivity extends Activity { 41 | private static final String TAG = "OAuthDemoActivity"; 42 | 43 | public static final Long appId = 179887661252608L; 44 | public static final String redirectUri = "http://xiaomi.com"; 45 | XiaomiOAuthResults results; 46 | private AsyncTask waitResultTask; 47 | 48 | @Override 49 | protected void onCreate(Bundle savedInstanceState) { 50 | super.onCreate(savedInstanceState); 51 | setContentView(R.layout.activity_main); 52 | ((EditText) findViewById(R.id.appId)).setText(String.valueOf(appId)); 53 | ((EditText) findViewById(R.id.redirectUrl)).setText(redirectUri); 54 | 55 | findViewById(R.id.get_token).setOnClickListener(new OnClickListener() { 56 | @Override 57 | public void onClick(View v) { 58 | boolean skipConfirm = ((CheckBox) findViewById(R.id.skipConfirm)).isChecked(); 59 | XiaomiOAuthFuture future = new XiaomiOAuthorize() 60 | .setAppId(getAppId()) 61 | .setRedirectUrl(getRedirectUri()) 62 | .setScope(getScopeFromUi()) 63 | .setKeepCookies(getTryKeepCookies()) // 不调的话默认是false 64 | .setNoMiui(getNoMiui()) // 不调的话默认是false,不建议设置 65 | .setSkipConfirm(skipConfirm) // 不调的话默认是false 66 | .setPhoneNumAutoFill(MainActivity.this.getApplicationContext(), true) 67 | // 自定义非miui上的登录界面,设置actionbar、进度条等 68 | //.setCustomizedAuthorizeActivityClass(CustomizedAuthorizedActivity.class) 69 | .startGetAccessToken(MainActivity.this); 70 | waitAndShowFutureResult(future); 71 | } 72 | }); 73 | 74 | findViewById(R.id.get_code).setOnClickListener(new OnClickListener() { 75 | 76 | @Override 77 | public void onClick(View v) { 78 | int[] scopes = getScopeFromUi(); 79 | boolean noMiui = getNoMiui(); 80 | boolean skipConfirm = ((CheckBox) findViewById(R.id.skipConfirm)).isChecked(); 81 | XiaomiOAuthFuture future = new XiaomiOAuthorize() 82 | .setAppId(getAppId()) 83 | .setRedirectUrl(getRedirectUri()) 84 | .setScope(scopes) 85 | .setKeepCookies(getTryKeepCookies()) // 不调的话默认是false 86 | .setNoMiui(getNoMiui()) // 不调的话默认是false 87 | .setSkipConfirm(skipConfirm) // 不调的话默认是false 88 | .setPhoneNumAutoFill(MainActivity.this.getApplicationContext(), true) 89 | .startGetOAuthCode(MainActivity.this); 90 | waitAndShowFutureResult(future); 91 | } 92 | 93 | }); 94 | 95 | findViewById(R.id.profile_btn).setOnClickListener(new OnClickListener() { 96 | @Override 97 | public void onClick(View v) { 98 | if (results == null){ 99 | Toast.makeText(MainActivity.this,"请先获取token",Toast.LENGTH_SHORT).show(); 100 | return; 101 | } 102 | XiaomiOAuthFuture future = new XiaomiOAuthorize() 103 | .callOpenApi(MainActivity.this, 104 | getAppId(), 105 | XiaomiOAuthConstants.OPEN_API_PATH_PROFILE, 106 | results.getAccessToken(), 107 | results.getMacKey(), 108 | results.getMacAlgorithm()); 109 | waitAndShowFutureResult(future); 110 | } 111 | 112 | }); 113 | 114 | findViewById(R.id.relation_btn).setOnClickListener(new OnClickListener() { 115 | @Override 116 | public void onClick(View v) { 117 | if (results == null){ 118 | Toast.makeText(MainActivity.this,"请先获取token",Toast.LENGTH_SHORT).show(); 119 | return; 120 | } 121 | XiaomiOAuthFuture future = new XiaomiOAuthorize() 122 | .callOpenApi(MainActivity.this, 123 | getAppId(), 124 | XiaomiOAuthConstants.OPEN_API_PATH_RELATION, 125 | results.getAccessToken(), 126 | results.getMacKey(), 127 | results.getMacAlgorithm()); 128 | waitAndShowFutureResult(future); 129 | } 130 | }); 131 | 132 | findViewById(R.id.openid_btn).setOnClickListener(new OnClickListener() { 133 | @Override 134 | public void onClick(View v) { 135 | if (results == null){ 136 | Toast.makeText(MainActivity.this,"请先获取token",Toast.LENGTH_SHORT).show(); 137 | return; 138 | } 139 | XiaomiOAuthFuture future = new XiaomiOAuthorize() 140 | .callOpenApi(MainActivity.this, 141 | getAppId(), 142 | XiaomiOAuthConstants.OPEN_API_PATH_OPEN_ID, 143 | results.getAccessToken(), 144 | results.getMacKey(), 145 | results.getMacAlgorithm()); 146 | waitAndShowFutureResult(future); 147 | } 148 | }); 149 | 150 | findViewById(R.id.phone_btn).setOnClickListener(new OnClickListener() { 151 | @Override 152 | public void onClick(View v) { 153 | if (results == null){ 154 | Toast.makeText(MainActivity.this,"请先获取token",Toast.LENGTH_SHORT).show(); 155 | return; 156 | } 157 | XiaomiOAuthFuture future = new XiaomiOAuthorize() 158 | .callOpenApi(MainActivity.this, 159 | getAppId(), 160 | XiaomiOAuthConstants.OPEN_API_PATH_PHONE, 161 | results.getAccessToken(), 162 | results.getMacKey(), 163 | results.getMacAlgorithm()); 164 | waitAndShowFutureResult(future); 165 | } 166 | }); 167 | 168 | findViewById(R.id.fast_oauth_btn).setOnClickListener(new OnClickListener() { 169 | @Override 170 | public void onClick(View v) { 171 | boolean skipConfirm = ((CheckBox) findViewById(R.id.skipConfirm)).isChecked(); 172 | 173 | XiaomiOAuthFuture future = new XiaomiOAuthorize() 174 | .setAppId(getAppId()) 175 | .setRedirectUrl(getRedirectUri()) 176 | .setScope(getScopeFromUi()) 177 | .setSkipConfirm(skipConfirm) // 不调的话默认是false 178 | .fastOAuth(MainActivity.this, XiaomiOAuthorize.TYPE_TOKEN); 179 | waitAndShowFutureResult(future); 180 | 181 | } 182 | }); 183 | 184 | if(savedInstanceState == null){ 185 | XiaomiOAuthFuture future = new XiaomiOAuthorize() 186 | .setAppId(getAppId()) 187 | .setRedirectUrl(getRedirectUri()) 188 | .setScope(getScopeFromUi()) 189 | .fastOAuth(MainActivity.this, XiaomiOAuthorize.TYPE_TOKEN); 190 | waitAndShowFutureResult(future); 191 | } 192 | 193 | requestPermission(); 194 | } 195 | 196 | private void requestPermission() { 197 | if (PermissionChecker.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PERMISSION_DENIED) { 198 | ActivityCompat.requestPermissions(this, 199 | new String[]{Manifest.permission.READ_PHONE_STATE}, 200 | 1000); 201 | } 202 | } 203 | 204 | @Override 205 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 206 | super.onActivityResult(requestCode, resultCode, data); 207 | if (requestCode == 1000 && PermissionChecker.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PERMISSION_DENIED) { 208 | finish(); 209 | } 210 | } 211 | 212 | private boolean getTryKeepCookies() { 213 | return ((CheckBox) findViewById(R.id.tryKeepCookies)).isChecked(); 214 | } 215 | 216 | private boolean getNoMiui() { 217 | return ((CheckBox) findViewById(R.id.nonMiui)).isChecked(); 218 | } 219 | 220 | private String getRedirectUri() { 221 | String uri = ((EditText) findViewById(R.id.redirectUrl)).getText().toString(); 222 | if (uri.isEmpty()) { 223 | return MainActivity.redirectUri; 224 | } 225 | return uri; 226 | } 227 | 228 | private Long getAppId() { 229 | String appId = ((EditText) findViewById(R.id.appId)).getText().toString(); 230 | if (appId.isEmpty()) { 231 | return MainActivity.appId; 232 | } 233 | return Long.valueOf(appId); 234 | } 235 | 236 | @Override 237 | public boolean onCreateOptionsMenu(Menu menu) { 238 | getMenuInflater().inflate(R.menu.main, menu); 239 | return true; 240 | } 241 | 242 | @Override 243 | public boolean onMenuItemSelected(int featureId, MenuItem item) { 244 | if (item.getItemId() == R.id.oldApiDemo) { 245 | // startActivity(new Intent(this, OldMainActivity.class)); 246 | } else if (item.getItemId() == R.id.customizeAuthorizeActivity) { 247 | XiaomiOAuthFuture future = new XiaomiOAuthorize() 248 | .setAppId(getAppId()) 249 | .setRedirectUrl(getRedirectUri()) 250 | .setNoMiui(true) // set to true only because we want to simulate behavior on Non-MIUI ROM. 251 | .setScope(getScopeFromUi()) 252 | .setCustomizedAuthorizeActivityClass(CustomizedAuthorizedActivity.class) 253 | .startGetAccessToken(this); 254 | waitAndShowFutureResult(future); 255 | } 256 | return super.onMenuItemSelected(featureId, item); 257 | } 258 | 259 | private int[] getScopeFromUi() { 260 | HashMap scopeMap = new HashMap(); 261 | scopeMap.put(R.id.scopeProfile, XiaomiOAuthConstants.SCOPE_PROFILE); 262 | scopeMap.put(R.id.scopeRelation, XiaomiOAuthConstants.SCOPE_RELATION); 263 | scopeMap.put(R.id.scopeOpenId, XiaomiOAuthConstants.SCOPE_OPEN_ID); 264 | scopeMap.put(R.id.scopePhone, XiaomiOAuthConstants.SCOPE_PHONE); 265 | 266 | int[] scopes = new int[scopeMap.size()]; 267 | int checkedCount = 0; 268 | 269 | for (Integer id : scopeMap.keySet()) { 270 | CheckBox cb = (CheckBox) findViewById(id); 271 | if (cb.isChecked()) { 272 | scopes[checkedCount] = scopeMap.get(id); 273 | checkedCount++; 274 | } 275 | } 276 | 277 | return Arrays.copyOf(scopes, checkedCount); 278 | } 279 | 280 | @Override 281 | protected void onDestroy() { 282 | super.onDestroy(); 283 | if(waitResultTask!=null && !waitResultTask.isCancelled()){ 284 | waitResultTask.cancel(false); 285 | } 286 | } 287 | 288 | @SuppressLint("StaticFieldLeak") 289 | private void waitAndShowFutureResult(final XiaomiOAuthFuture future) { 290 | waitResultTask = new AsyncTask() { 291 | Exception e; 292 | 293 | @Override 294 | protected void onPreExecute() { 295 | showResult("waiting for Future result..."); 296 | } 297 | 298 | @Override 299 | protected V doInBackground(Void... params) { 300 | showResult("waiting for Future result getting..."); 301 | V v = null; 302 | try { 303 | v = future.getResult(); 304 | } catch (IOException e1) { 305 | this.e = e1; 306 | } catch (OperationCanceledException e1) { 307 | this.e = e1; 308 | } catch (XMAuthericationException e1) { 309 | this.e = e1; 310 | } 311 | return v; 312 | } 313 | 314 | @Override 315 | protected void onPostExecute(V v) { 316 | if (v != null) { 317 | if (v instanceof XiaomiOAuthResults) { 318 | results = (XiaomiOAuthResults) v; 319 | } 320 | showResult(v.toString()); 321 | } else if (e != null) { 322 | showResult(e.toString()); 323 | } else { 324 | showResult("done and ... get no result :("); 325 | } 326 | } 327 | }.executeOnExecutor(mExecutor); 328 | } 329 | 330 | Executor mExecutor = Executors.newCachedThreadPool(); 331 | 332 | private void showResult(final String text) { 333 | runOnUiThread(new Runnable() { 334 | @Override 335 | public void run() { 336 | String timeFormatted = new SimpleDateFormat("HH:mm:ss:SSS").format(new Date(System.currentTimeMillis())); 337 | ((TextView) findViewById(R.id.content)).setText(timeFormatted + "\n" + text); 338 | Log.v(TAG, "result:" + text); 339 | } 340 | }); 341 | } 342 | } 343 | -------------------------------------------------------------------------------- /sample/app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaomi-passport/oauth-android-sdk/ef257668a5c757655daa7804c64676d4154a5f93/sample/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/app/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaomi-passport/oauth-android-sdk/ef257668a5c757655daa7804c64676d4154a5f93/sample/app/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/app/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaomi-passport/oauth-android-sdk/ef257668a5c757655daa7804c64676d4154a5f93/sample/app/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaomi-passport/oauth-android-sdk/ef257668a5c757655daa7804c64676d4154a5f93/sample/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 12 | 13 | 14 | 18 | 19 | 24 | 25 | 29 | 30 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 50 | 51 | 56 | 61 | 62 | 67 | 68 | 73 | 74 | 79 | 80 | 85 | 86 | 87 | 88 | 93 | 94 | 102 | 103 | 53 | 54 |