google oauth认证与使用youtube的api-2,tv版本

发布时间:2023年12月24日

上文写上了如何通过认证,得到token,与访问youtube的api

本文写一些其它方面的应用.

token的刷新

public interface AuthApi {
    @Headers("Content-Type: application/json")
    @POST("https://www.youtube.com/o/oauth2/device/code")
    Call<UserCode> getUserCode(@Body String authQuery);

    @Headers("Content-Type: application/json")
    @POST("https://www.youtube.com/o/oauth2/token")
    Call<RefreshToken> getRefreshToken(@Body String authQuery);

    @Headers("Content-Type: application/json")
    @POST("https://www.youtube.com/o/oauth2/token")
    Call<AccessToken> getAccessToken(@Body String authQuery);

    @Headers("Content-Type: application/json")
    @POST("https://www.youtube.com/youtubei/v1/account/accounts_list")
    Call<AccountsList> getAccountsList(@Body String authQuery);
}

这是接口的声明.然后直接用它就可以了.申请key这些就不详细说了.

本文主要是涉及tv版本的开发,tv与手机不同,如果使用app-auth上的认证过程,在tv上,会因为多数摇控器无法点击而失败,有些遥控器是可以出现鼠标的.

谷歌官方提供了一种tv 认证的方式,申请凭据的时候,要选tv,官方文档也有相关的说明.最近youtube的官方文档已经没有了示例了,前一周变的...

public class AuthApiHelper {
    private static final String USER_CODE = "{\"client_id\":\"%s\",\"device_id\":\"%s\",\"model_name\":\"%s\",\"scope\":\"%s\"}";
    private static final String REFRESH_TOKEN = "{\"code\":\"%s\",\"client_id\":\"%s\",\"client_secret\":\"%s\",\"grant_type\":\"%s\"}";
    private static final String ACCESS_TOKEN = "{\"refresh_token\":\"%s\",\"client_id\":\"%s\",\"client_secret\":\"%s\",\"grant_type\":\"%s\"}";
    //private static final String APP_SCOPE = "http://gdata.youtube.com https://www.googleapis.com/auth/youtube-paid-content";
    private static final String GRANT_TYPE_DEFAULT = "http://oauth.net/grant_type/device/1.0";
    private static final String GRANT_TYPE_REFRESH = "refresh_token";
    private static final String MODEL_NAME = "ytlr::";

    //public static String getAccountsListQuery() {
    //    return ServiceHelper.createQueryTV("\"accountReadMask\":{\"returnOwner\":true,\"returnBrandAccounts\":true,\"returnPersonaAccounts\":false}");
    //}

    public static String getUserCodeQuery(String clientId) {
        return String.format(USER_CODE, clientId, MediaServiceData.instance().getDeviceId(), MODEL_NAME, "openid email profile https://www.googleapis.com/auth/youtube");
    }

    public static String getRefreshTokenQuery(String deviceCode, String clientId, String clientSecret) {
        return String.format(REFRESH_TOKEN, deviceCode, clientId, clientSecret, GRANT_TYPE_DEFAULT);
    }

    public static String getAccessTokenQuery(String refreshToken, String clientId, String clientSecret) {
        return String.format(ACCESS_TOKEN, refreshToken, clientId, clientSecret, GRANT_TYPE_REFRESH);
    }
}

这段代码就是设置了请示内容,scope要email, profile与youtube,前面两个是得到邮箱,用户名信息.后面是访问youtube的内容.

但是,认证过程,发现了,没有得到用户信息,只得到了邮箱,是在idtoken里面的.

Call<UserCode> wrapper = mAuthApi.getUserCode(
                AuthApiHelper.getUserCodeQuery(clientId)
        );

这是调用认证的方法.

开始认证了.UserCode userCodeResult = mAuthService.getUserCode();

在rxjava里面容易实现,这个调用成功后就调用onnext.然后接着出现什么呢?就是让手机去打开相应的地址,进行认证.这个手机的地址应该是什么样的

tv上如何认证

private static final String SIGN_IN_URL_FULL = "https://youtube.com/tv/activate"; // support query params

    private void updateUI(String userCode, String url) {
        if (TextUtils.isEmpty(userCode)) {
            return;
        }

        user_code.setText(userCode);

        Glide.with(this)
                .load(Utils.toQrCodeLink(SIGN_IN_URL_FULL + "?user_code=" + userCode.replace(" ", "-")))
                //.load(Utils.toQrCodeLink(url))
                .apply(ViewUtil.glideOptions()).error(ContextCompat.getDrawable(this, R.drawable.activate_account_qrcode))
                //.listener(mErrorListener)
                .into(img_code);
    }

上面得到的usecode得到,里面会有一个code,这个code是用于手机认证里面的输入框中的内容,这里的方式是生成一个二维码,然后手机一扫,就直接过去了.二维码的生成

private static final String QR_CODE_URL_TEMPLATE = "https://api.qrserver.com/v1/create-qr-code/?data=%s";data就是链接内容

可以参考官方文档与二维码的图片,最终展示出来就可以了.

展示后的逻辑,官方文档说明,刷新token的接口,直到得到token. 上面拼接的地址可以不使用这个url,使用另一个SIGN_IN_URL_FULL,这个可以带参数 ,把code带过去,否则用户还要手输入

刷新token就是上面api中的getRefreshToken接口.传的参数oauth2都一样.大概就是private static final String REFRESH_TOKEN = "{\"code\":\"%s\",\"client_id\":\"%s\",\"client_secret\":\"%s\",\"grant_type\":\"%s\"}";这样的东西了.

手机是没有client_secret,但web与tv是有的.

如果手机扫码后一直没有登录,那么这个接口刷不到数据.

得到token后,获取用户信息等

有了token,用户数据是如何获取的.smarttube里面是通过getAccountsList,这个比较复杂,有更简单的方法.

private boolean getUserInfo(String accessToken, YouTubeAccount account) {
        try {
            String url = "https://openidconnect.googleapis.com/v1/userinfo";
            HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
            conn.setConnectTimeout(CONNECTION_TIMEOUT_MS);
            conn.setReadTimeout(READ_TIMEOUT_MS);
            conn.setInstanceFollowRedirects(false);
            conn.setRequestProperty("Authorization", "Bearer " + accessToken);
            conn.setInstanceFollowRedirects(false);
            String response = Okio.buffer(Okio.source(conn.getInputStream())).readString(StandardCharsets.UTF_8);
            Log.d(TAG, "user:" + response);
            JSONObject jo = new JSONObject(response);
            account.setEmail(jo.optString("email"));
            account.setName(jo.optString("name"));
            account.setImageUrl(jo.optString("picture"));
            return true;
        } catch (IOException ioEx) {
            Log.e(TAG, "Network error when querying userinfo endpoint", ioEx);
        } catch (Exception jsonEx) {
            Log.e(TAG, "Failed to parse userinfo response");
        }
        return false;
    }

这个接口就是app-auth里面获取用户信息得到的,本来想的是idtoken解析一下,它是ba

se64编码,但发现上面token里面的idtoken并没有包含到这些东西,只有邮箱.

而这个接口可以有邮箱,用户名,头像等

在smarttube中,使用了200次循环.

到这里,在tv上认证,得到token,通过token,得到用户信息的整个过程就完成了.

剩下的就是使用这个token.但只有一个小时的时效,所以在每次调用接口前去检测一下是否超时.这是个缺点

参考的项目,资料

smarttube,在github上有源码,

后续会写一些关于tv上如何使用leanback这个库,做一个简单实用的tv应用

文章来源:https://blog.csdn.net/archko/article/details/135178657
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。