 

授权登录功能的实现主要是通过智汀云盘App发起一个携带要获取权限参数的意图去启动智汀App,智汀App根据权限参数获取相应的授权信息(包括家庭信息、用户信息和登录凭证)并通过广播发送消息,智汀云盘接收到广播消息之后进行保存授权信息和登录操作,当然进入智汀App之后的那个家庭,必须是有绑定SA的家庭。
1) 智汀云盘主要代码实现:
/**
 * 登录界面
 */
public class LoginActivity extends BaseMVPDBActivity<ActivityLoginBinding, LoginContract.View, LoginPresenter> implements  LoginContract.View {
    private String mUri = "zt://com.yctc.zhiting/sign?type=1&user_package_name=com.yctc.zhiting";  // 启动智汀App地址
    private MyBroadcastReceiver mReceiver;  // 授权登录广播
    ...
    @Override
    protected void initData() {
        super.initData();
        //注册广播接受者,接收授权成功返回广播信息
        mReceiver = new MyBroadcastReceiver();
        IntentFilter intentFilter = new IntentFilter();
        //zt.com.yctc.zhiting.sign 自行定义action 即可
        intentFilter.addAction("zt.com.yctc.zhiting.sign");
        registerReceiver(mReceiver, intentFilter);
        if (!TextUtils.isEmpty(SpUtil.getString("loginInfo"))){
            toMain(SpUtil.getString("loginInfo"), false);
        }
    }
    
    ...
    
    /**
     * 点击事件
     */
    public class OnClickHandler{
        public void onClick(View view){
            int viewId = view.getId();
            if (viewId == R.id.tvLogin){ // 登录
                if (AppUtil.isMobile_spExist(CDApplication.getContext(), "com.yctc.zhiting")) {  // 已安装智汀,执行授权登录
                    LogUtil.d("=================登录============");
                    Intent intent = new Intent();
                    intent.setData(Uri.parse(mUri));//参数拼接在URI后面 type=1是授权页面,user_package_name使用者包名,后续参数可自行添加
                    intent.putExtra("needPermissions", "user,area");//这里Intent也可传递参数,但是一般情况下都会放到上面的URL中进行传递
                    intent.putExtra("appName", UiUtil.getString(R.string.to_third_party_name));
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(intent);
                }else {  // 未安装智汀,提示用户安装
                    ToastUtil.show(getResources().getString(R.string.main_please_install_zhiting));
                }
            }
        }
    }
    /**
     * 接收授权登录广播
     */
    private class MyBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            //  授权成功之后返回的信息
            String backInfo = intent.getStringExtra("backInfo");
            SpUtil.put("loginInfo", backInfo);
            toMain(backInfo, true);
        }
    }
    /**
     * 去主界面
     * @param json
     */
    private void toMain(String json, boolean delay){
        Constant.authBackBean = GsonConverter.getGson().fromJson(json, AuthBackBean.class);  // 授权信息
        if (Constant.authBackBean!=null) {
            HomeCompanyBean homeCompanyBean = Constant.authBackBean.getHomeCompanyBean();  // 家庭
            if (homeCompanyBean!=null) {
                String url = homeCompanyBean.getSa_lan_address();
                if (!TextUtils.isEmpty(url)) {
                    HttpConfig.baseUrl = homeCompanyBean.getSa_lan_address();
                    HttpConfig.baseTestUrl = homeCompanyBean.getSa_lan_address();
                    HttpConfig.uploadFileUrl = HttpConfig.baseTestUrl+HttpConfig.uploadFileUrl;
                    HttpConfig.downLoadFileUrl = HttpConfig.baseTestUrl+HttpConfig.downLoadFileUrl;
                    HttpConfig.downLoadFolderUrl1 = HttpConfig.baseTestUrl+HttpConfig.downLoadFolderUrl1;
                    HttpConfig.downLoadFolderUrl2 = HttpConfig.baseTestUrl+HttpConfig.downLoadFolderUrl2;
                }
                Constant.HOME_NAME = homeCompanyBean.getName();
            }
            Constant.cookies = Constant.authBackBean.getCookies();
            Constant.scope_token = Constant.authBackBean.getStBean().getToken();  // scopeToken
            Constant.USER_ID = Constant.authBackBean.getUserId();  // 用户 id
            Constant.userName = Constant.authBackBean.getUserName();  // 用户名称
            if (delay) {  // 是否需要延时, 主要解决oppo没有跳转到主界面,直接到桌面的问题
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            switchToActivity(MainActivity.class);
            finish();
        }
    }
}
2) 智汀主要代码实现:
/**
  * 启动页
  */
 public class SplashActivity extends BaseActivity {
 
     ...
 
     /**
      * 1 授权登录
      */
     private String type;
     /**
      * 第三方应用需要的权限
      */
     private String needPermissions;
     /**
      * 第三方app的名称
      */
     private String appName;
     
     ...
         
     @Override
     protected void initIntent(Intent intent) {
         super.initIntent(intent);
         Uri uri = intent.getData();
         if (uri != null) {
             type = uri.getQueryParameter("type");
         }
         needPermissions = intent.getStringExtra("needPermissions");
         appName = intent.getStringExtra("appName");
         if (type!=null && type.equals("1") && CurrentHome!=null){  // 如果是授权过来且当前家庭不为空,直接调整授权界面
             Bundle bundle = new Bundle();
             bundle.putString(IntentConstant.NEED_PERMISSION, needPermissions);
             bundle.putString(IntentConstant.APP_NAME, appName);
             // 如果type不为空且为1的情况下到授权界面,否则直接到主界面
             switchToActivity(AuthorizeActivity.class, bundle);
             finish();
         }else { // 否则,正常流程
             checkPermissionTask();
         }
     }
     
     ...
         
     /**
      * 去到主界面/授权界面
      */
     private void toMain() {
         UiUtil.starThread(() -> {
             List<HomeCompanyBean> homeList = dbManager.queryHomeCompanyList();
             if (CollectionUtil.isNotEmpty(homeList)){
             CurrentHome = homeList.get(0);
             UiUtil.runInMainThread(() -> {
                 if (wifiInfo != null) {
                     for (HomeCompanyBean home : homeList) {
                         if (HomeFragment.homeLocalId > 0){  // 之前打开过,没退出,按Home键之前的那个家庭
                             if (home.getLocalId() == HomeFragment.homeLocalId){
                                 CurrentHome = home;
                                 break;
                             }
                         }
                         if (home.getMac_address() != null && home.getMac_address().
                                 equalsIgnoreCase(wifiInfo.getBSSID()) && home.isIs_bind_sa()) { // 当前sa环境
                             CurrentHome = home;
                             break;
                         }
                     }
                 }
                 UiUtil.postDelayed(() -> {
                     Bundle bundle = new Bundle();
                     bundle.putString(IntentConstant.TYPE, type); 
                     bundle.putString(IntentConstant.NEED_PERMISSION, needPermissions);
                     bundle.putString(IntentConstant.APP_NAME, appName);
                     // 如果type不为空且为1的情况下到授权界面,否则直接到主界面
                     switchToActivity(type!=null && type.equals("1") ? AuthorizeActivity.class : MainActivity.class, bundle); 
                     finish();
                 }, 1500);
             });
 
             }
 
         });
     }
     .../**
* 授权界面
*/
public class AuthorizeActivity extends MVPBaseActivity<AuthorizeContract.View, AuthorizePresenter> implements AuthorizeContract.View {
   @BindView(R.id.tvName)
   TextView tvName;
   @BindView(R.id.tvJoin)
   TextView tvJoin;
   @BindView(R.id.rvScopes)
   RecyclerView rvScopes;
   @BindView(R.id.tvTips)
   TextView tvTips;
   /**
    * 第三方应用需要的权限
    */
   private String needPermissions;
   /**
    * 第三方app的名称
    */
   private String appName;
   private ScopesAdapter scopesAdapter;
   private Handler mainThreadHandler;
   private DBManager dbManager;
   private WeakReference<Context> mContext;
   private int userId;
   private String userName;  // 用户名称
   private String[] permissions; // 同意授权的信息
   
   ...
   @Override
   protected void initData() {
       super.initData();
       mContext = new WeakReference<>(getActivity());
       dbManager = DBManager.getInstance(mContext.get());
       mainThreadHandler = new Handler(Looper.getMainLooper());
       getUserInfo();
        permissions = needPermissions.split(",");
        // 同意授权的信息数据
        List<ScopesBean.ScopeBean> data = new ArrayList<>();
        if (permissions.length>0){
            for (int i=0; i<permissions.length; i++){
                if (permissions[i].equals(Constant.USER)){
                    data.add(new ScopesBean.ScopeBean(Constant.USER, getResources().getString(R.string.main_get_login_status)));
                }else if (permissions[i].equals(Constant.AREA)){
                    data.add(new ScopesBean.ScopeBean(Constant.AREA, getResources().getString(R.string.main_get_family_info)));
                }
            }
        }
       scopesAdapter.setNewData(data);
   }
   ...
   @OnClick(R.id.tvConfirm)
   void onClickConfirm(){
       if (TextUtils.isEmpty(Constant.CurrentHome.getSa_user_token())){  // 当前家庭没有绑定SA
           ToastUtil.show(UiUtil.getString(R.string.main_home_is_not_bind_with_sa));
       }else {  // 当前家庭绑了SA
           // 获取token的请求参数
           List<String> scopes = new ArrayList<>();
           for (String permission : permissions){
               scopes.add(permission);
           }
           ScopeTokenRequest scopeTokenRequest = new ScopeTokenRequest(scopes);
           // 获取token接口
           mPresenter.getScopeToken(scopeTokenRequest.toString());
       }
   }
   /**
    * 获取 SCOPE 列表成功
    * @param scopesBean
    */
   @Override
   public void getScopesSuccess(ScopesBean scopesBean) {
       if (scopesBean!=null){
           if (CollectionUtil.isNotEmpty(scopesBean.getScopes())){
               List<ScopesBean.ScopeBean> data = new ArrayList<>();
               if (!TextUtils.isEmpty(needPermissions)) {
                   for (ScopesBean.ScopeBean scopeBean : scopesBean.getScopes()) {
                       for (String permission : permissions){
                           if (scopeBean.getName().equals(permission)){
                               data.add(scopeBean);
                           }
                       }
                   }
                   scopesAdapter.setNewData(data);
               }
           }
       }
   }
   @Override
   public void getScopesFail(int errorCode, String msg) {
       ToastUtil.show(msg);
   }
   /**
    * 获取 SCOPE Token成功
    * @param scopeTokenBean
    */
   @Override
   public void getScopeTokenSuccess(ScopeTokenBean scopeTokenBean) {
       if (scopeTokenBean!=null){
           ScopeTokenBean.STBean  stBean = scopeTokenBean.getScope_token();
           if (stBean!=null){
               Intent intent = new Intent();
               AuthBackBean authBackBean = new AuthBackBean(Constant.CurrentHome.getUser_id(), userName, Constant.CurrentHome, stBean);
               if (UserUtils.isLogin()){
                   authBackBean.setCookies(PersistentCookieStore.getInstance().get(HttpUrl.parse(HttpUrlConfig.getLogin())));
               }else {
                   authBackBean.setCookies(new ArrayList<>());
               }
               intent.setAction("zt.com.yctc.zhiting.sign");
               intent.putExtra("backInfo", authBackBean.toString());
               sendBroadcast(intent);
               LibLoader.finishAllActivity();
           }else {
               ToastUtil.show(UiUtil.getString(R.string.main_login_fail));
           }
       }else {
           ToastUtil.show(UiUtil.getString(R.string.main_login_fail));
       }
   }
   @Override
   public void getScopeTokenFail(int errorCode, String msg) {
       ToastUtil.show(msg);
   }
   ...
}
3) 还有最重要的一点是需要在智汀的清单文件为其他App/浏览器提供入口:
<activity android:name=".activity.SplashActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <data
                    android:host="com.yctc.zhiting"
                    android:path="/sign"
                    android:scheme="zt" />
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
  </activity>
4) 授权信息类:
/**
 * 授权信息类
 */
public class AuthBackBean extends Request {
    private int userId;  // 用户id
    private String userName; // 用户昵称
    private HomeCompanyBean homeCompanyBean; // 家庭信息
    private ScopeTokenBean.STBean stBean; // 授权token和过期时间
    private List<Cookie> cookies; // 登录SC时的cookie
    ...
}
public class HomeCompanyBean {
    private int id;//云端家庭id
    private int roomAreaCount;//房间个数
    private int location_count;  // 房间数量
    private int role_count;  // 角色数量
    private int user_count; // 成员数量
    @SerializedName("sa_user_id")
    private int user_id; // sa用户id
    private boolean is_bind_sa;  //是否绑定sa
    private boolean selected; // 标识是否被选中
    private String name;//家庭名称
    private String sa_lan_address; // sa地址
    private String sa_user_token;  // sa token
    private String ss_id;//wifi id
    private String mac_address;//wifi地址
    
    ...
}
public class ScopeTokenBean {
    /**
     * scope_token : {"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MjgyNDc2NzgsInNhX2lkIjoidGVzdC1zYS10ZXN0Iiwic2NvcGVzIjoidXNlcixhcmVhIiwidWlkIjozfQ.HM_pLMTYw_Yzz4kWQIERWU9FnmP6SM_ejV1M0GMXbAc","expires_in":2592000}
     */
    private STBean scope_token;
    ...
    public static class STBean {
        /**
         * token : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MjgyNDc2NzgsInNhX2lkIjoidGVzdC1zYS10ZXN0Iiwic2NvcGVzIjoidXNlcixhcmVhIiwidWlkIjozfQ.HM_pLMTYw_Yzz4kWQIERWU9FnmP6SM_ejV1M0GMXbAc
         * expires_in : 2592000
         */
        private String token;
        private int expires_in;  // 有效期,单位为秒
        
        ...
    }
}










