ニコニコAPI仕様いろいろ | にっき

にっき

Android開発してます。

デバッグで色々調べたら混乱してきたので、備忘録も兼ねて整理する
今回調べたのは「getflvでurl取得して、そこから動画取得する」という箇所
色々な処理の途中で(PCから)ログイン切断してみた。

【前提】
視聴ページ
ログイン情報(user-session) が必須

getflv
ログイン情報(user-session) が必須

動画本体取得
視聴情報(nicohistory)
ログイン情報(user-session) が必須


【実験内容・結果】
1.視聴ページリクエスト時にログイン切断
→nicohistoryがCookieに返却されない

2.getflvリクエスト時にログイン切断
→urlがレスポンスに存在しない

3.動画本体取得時にログイン切断
→正常に動画を取得


1,2は予想通りだけど、3が予想外だった
結果から書くと、

正常なログイン情報(user-session)
動画url
nicohistoryがあれば

それぞれがどうであれ、また、外部でどうなってようが関係なく取得できるみたい。

--------------------------------

ここからが混乱した所だが、

1でnicohistoryを取得する際に利用したログイン情報と
2でurlを取得する際に利用するログイン情報は 同じである必要がなく(※1)
3ではそれぞれ必要なデータが取り敢えずあれば良いってこと

※1…ユーザーは同じ。異なるユーザー情報で行けたらヤバイと思う。

1 nicohistory取得
2で切断
2リトライ(1とuser-sessionが変わる)
3で切断(内部で1のnicohistory, 2の新user-sessionは保持、外部では切断状態)
ってやっても、取得できたし。


【結論】

というわけで、実装する際は
それぞれの情報を取得する際に、結果が不正なら
ログイン情報を再取得してリトライすれば良い。

【感想】
最初、全情報取得時に一貫したログイン情報が必要だと思ってたから混乱した。
意外と簡単なつくりなのか?同じユーザーなら何でも良いっぽいな。
難しく考えすぎたみたいだわ。アホらし。

結局、ログインして視聴ページ開いて、動画保管場所URL持ってれば勝ち確ってことか…



以下ソース
@Override
  protected Integer doInBackground(Void... unused) {
    SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mActivity);
    // ログイン情報取得
    BasicClientCookie loginCookie =
        new BasicClientCookie(Config.COOKIE_NAME_LOGIN, sp.getString(Config.COOKIE_NAME_LOGIN, null));
    loginCookie.setDomain(Config.COOKIE_DOMAIN);
    loginCookie.setPath(Config.COOKIE_PATH);


    // 視聴ページへアクセス
    NicoHelper nicoHelper = new NicoHelper(mActivity);
    Cookie watchCookie = nicoHelper.getWatchCookie(loginCookie);
    if (watchCookie == null) {
      // 視聴クッキーが不正ならログイン情報をリセットしてリトライ
      sp.edit().remove(Config.COOKIE_NAME_LOGIN).commit();
      if (nicoHelper.login() == Config.STATUS_OK) {
        loginCookie = new BasicClientCookie(Config.COOKIE_NAME_LOGIN, sp.getString(Config.COOKIE_NAME_LOGIN, null));
        loginCookie.setDomain(Config.COOKIE_DOMAIN);
        loginCookie.setPath(Config.COOKIE_PATH);
        watchCookie = nicoHelper.getWatchCookie(loginCookie); // 視聴クッキー取得リトライ
        if (watchCookie == null) {
          return null; // 2回目の視聴もNGなら終了
        }
      } else {
        return null;
      }
    }


    // 動画保管場所へアクセス
    HttpRequestHelper httpRequestHelperForFlv = new HttpRequestHelper();
    httpRequestHelperForFlv.setCookie(loginCookie);
    HttpResponse flvResponse = httpRequestHelperForFlv.getRequest(Config.FLASH_API_URL);
    if (flvResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
      return null;
    }


    // レスポンスデータへの処理
    InputStream flvStream = null;
    InputStream movieStream = null;
    try {
      flvStream = flvResponse.getEntity().getContent();
      HashMap flvInfoMap =
          HttpRequestHelper.getResponseMap(HttpRequestHelper.getResponseString(flvStream));
      String movieUrl = flvInfoMap.get("url");
      if (movieUrl == null) {
        // 動画保管場所へのアクセスがNGならログイン情報をリセットしてリトライ
        sp.edit().remove(Config.COOKIE_NAME_LOGIN).commit();
        if (nicoHelper.login() == Config.STATUS_OK) {
          loginCookie = new BasicClientCookie(Config.COOKIE_NAME_LOGIN, sp.getString(Config.COOKIE_NAME_LOGIN, null));
          loginCookie.setDomain(Config.COOKIE_DOMAIN);
          loginCookie.setPath(Config.COOKIE_PATH);
          httpRequestHelperForFlv.setCookie(loginCookie);
          flvResponse = httpRequestHelperForFlv.getRequest(Config.FLASH_API_URL);
          if (flvResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
            return null;
          }
          flvStream = flvResponse.getEntity().getContent();
          flvInfoMap = HttpRequestHelper.getResponseMap(HttpRequestHelper.getResponseString(flvStream));
          movieUrl = flvInfoMap.get("url");
          if (movieUrl == null) {
            return null; // 2回目もNGなら終了
          }
        } else {
          return null;
        }
      }
      // 動画取得(ここまで正常に来ていれば、外部ログアウトされても取得可能)
      HttpRequestHelper movieHttpRequestHelper = new HttpRequestHelper();
      movieHttpRequestHelper.setCookie(loginCookie); // ログインクッキー設定
      movieHttpRequestHelper.setCookie(watchCookie); // 視聴クッキー設定
      movieHttpRequestHelper.addHeader("Range", "bytes=0-1024000"); // ヘッダー設定
      HttpResponse movieResponse = movieHttpRequestHelper.getRequest(movieUrl); // ダウンロードリクエスト
      if (movieResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK
          && movieResponse.getStatusLine().getStatusCode() != HttpStatus.SC_PARTIAL_CONTENT) {
        return null;
      }
      movieStream = movieResponse.getEntity().getContent();
      downloadFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES), movieStream, "nico.mp4");


      // 通信終了
      httpRequestHelperForFlv.closeConnection();
      movieHttpRequestHelper.closeConnection();


      return Config.STATUS_OK;
    } catch (IllegalStateException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (flvStream != null) {
        try {
          flvStream.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
      if (movieStream != null) {
        try {
          movieStream.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
    return null;
  }