android youtube api v3 不适用于发行版

android youtube api v3 not work on release version

首先让我们从我的代码开始,我用于根据用户的搜索查询获取视频列表

public class YouTubeVideoLoader extends AsyncTask<String, Void, List<YouTubeVideo>>
{
private static final String TAG = LogHelper.makeLogTag(YouTubeVideoLoader.class);

private Context context;
private YouTube youtube;

private YouTube.Search.List searchList;

private String keywords;
private String currentPageToken;
private String nextPageToken;

private YouTubeVideoReceiver youTubeVideoReceiver;

private String language;

public YouTubeVideoLoader(Context context)
{
    getInstance(context);
    this.context = context;
    this.youtube = getYouTube();
    this.keywords = null;
    this.currentPageToken = null;
    this.nextPageToken = null;
    this.youTubeVideoReceiver = null;
    this.language = Locale.getDefault().getLanguage();
}

@Override
protected List<YouTubeVideo> doInBackground(String... params)
{
    if (keywords == null) return null;
    try {
        return searchVideos();
    } catch (Exception e) {
        e.printStackTrace();
    }

    return null;
}

@Override
protected void onPostExecute(List<YouTubeVideo> ytVideos)
{
    youTubeVideoReceiver.onVideosReceived(ytVideos, currentPageToken, nextPageToken);
}

/**
 * Start the search.
 *
 * @param keywords - query
 */
public void search(String keywords)
{
    this.keywords = keywords;
    this.currentPageToken = null;
    this.nextPageToken = null;
    this.execute();
}

/**
 * Start the search.
 *
 * @param keywords         - query
 * @param currentPageToken - contains the Page Token
 */
public void search(String keywords, String currentPageToken)
{
    this.keywords = keywords;
    this.currentPageToken = currentPageToken;
    this.nextPageToken = null;
//        this.execute();
    this.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
}

public void setYouTubeVideoReceiver(YouTubeVideoReceiver youTubeVideoReceiver)
{
    this.youTubeVideoReceiver = youTubeVideoReceiver;
}

/**
 * Search videos for a specific query
 */
private List<YouTubeVideo> searchVideos()
{

    
    List<YouTubeVideo> ytVideos = new ArrayList<>();
    try {
        searchList = youtube.search().list(YOUTUBE_SEARCH_LIST_PART);
        searchList.setKey(Config.YOUTUBE_API_KEY);
        searchList.set("key",Config.YOUTUBE_API_KEY);
        searchList.setQ(keywords);
        searchList.setType(YOUTUBE_SEARCH_LIST_TYPE); //TODO ADD PLAYLISTS SEARCH
        searchList.setMaxResults(Config.MAX_VIDEOS_RETURNED);
        searchList.setFields(YOUTUBE_SEARCH_LIST_FIELDS);
        searchList.set(YOUTUBE_LANGUAGE_KEY, language);
        if (currentPageToken != null) {
            searchList.setPageToken(currentPageToken);
        }


       

        final Pattern pattern = Pattern.compile(YT_REGEX);
        final Matcher matcher = pattern.matcher(keywords);

        if (matcher.find()) {

            Log.e(TAG, "YouTube ID: " + matcher.group(1));

            YouTube.Videos.List singleVideo = youtube.videos().list(YOUTUBE_VIDEO_PART);
            singleVideo.setKey(Config.YOUTUBE_API_KEY);
            searchList.set("key",Config.YOUTUBE_API_KEY);
            singleVideo.setFields(YOUTUBE_VIDEO_FIELDS);
            singleVideo.set(YOUTUBE_LANGUAGE_KEY, language);
            singleVideo.setId(matcher.group(1));
            VideoListResponse resp = singleVideo.execute();
            List<Video> videoResults = resp.getItems();

            for (Video videoResult : videoResults) {
                YouTubeVideo item = new YouTubeVideo();

                if (videoResult != null) {
                    // SearchList list info
                    item.setTitle(videoResult.getSnippet().getTitle());
                    item.setThumbnailURL(videoResult.getSnippet().getThumbnails().getDefault().getUrl());
                    item.setId(videoResult.getId());

                    // Video info
                    if (videoResult.getStatistics() != null) {
                        BigInteger viewsNumber = videoResult.getStatistics().getViewCount();
                        String viewsFormatted = NumberFormat.getIntegerInstance().format(viewsNumber) + " views";
                        item.setViewCount(viewsFormatted);
                    }
                    if (videoResult.getContentDetails() != null) {
                        String isoTime = videoResult.getContentDetails().getDuration();
                        String time = Utils.convertISO8601DurationToNormalTime(isoTime);
                        item.setDuration(time);
                    }
                } else {
                    item.setDuration("NA");
                }

                // Add to the list
                ytVideos.add(item);
            }
        } else {

            YouTube.Videos.List videosList = youtube.videos().list(YOUTUBE_VIDEO_LIST_PART);

            videosList.setKey(Config.YOUTUBE_API_KEY);
            searchList.set("key",Config.YOUTUBE_API_KEY);
            videosList.setFields(YOUTUBE_VIDEO_LIST_FIELDS);

            videosList.set(YOUTUBE_LANGUAGE_KEY, language);


            
            final SearchListResponse searchListResponse = searchList.execute();

       

           
            Log.e(TAG, "Printed " + searchListResponse.getPageInfo().getResultsPerPage() +
                    " out of " + searchListResponse.getPageInfo().getTotalResults() +
                    ".\nCurrent page token: " + searchList.getPageToken() + "\n" +
                    "Next page token: " + searchListResponse.getNextPageToken() +
                    ".\nPrev page token: " + searchListResponse.getPrevPageToken());

             
            final List<SearchResult> searchResults = searchListResponse.getItems();

            // Stores the nextPageToken
            nextPageToken = searchListResponse.getNextPageToken();
            
            // Finds video list
            videosList.setId(Utils.concatenateIDs(searchResults));
            VideoListResponse resp = videosList.execute();
            List<Video> videoResults = resp.getItems();

            // Create the ytVideos list to be displayed in the UI
            

            int index = 0;
            for (SearchResult result : searchResults) {
                if (result.getId() == null) {
                    continue;
                }

                YouTubeVideo item = new YouTubeVideo();

                String title = StringUtils.unescapeHtml3(result.getSnippet().getTitle());
                LogHelper.e(TAG, "Title: " + title);
                // SearchList list info
                item.setTitle(title);
                item.setThumbnailURL(result.getSnippet().getThumbnails().getDefault().getUrl());
                item.setId(result.getId().getVideoId());

                // Video info
                Video videoResult = videoResults.get(index);
                if (videoResult != null) {
                    if (videoResult.getStatistics() != null) {
                        BigInteger viewsNumber = videoResult.getStatistics().getViewCount();
                        String viewsFormatted = NumberFormat.getIntegerInstance().format(viewsNumber) + " views";
                        item.setViewCount(viewsFormatted);
                    }
                    if (videoResult.getContentDetails() != null) {
                        String isoTime = videoResult.getContentDetails().getDuration();
                        String time = Utils.convertISO8601DurationToNormalTime(isoTime);
                        item.setDuration(time);
                    }
                } else {
                    item.setDuration("NA");
                }

                // Add to the list
                ytVideos.add(item);
                index++;

            }
        }
    } catch (Exception e) {
        Log.e(TAG, "catch Could not initialize: " + e);
        e.printStackTrace();
    }

    Log.e(TAG, "LoadInBackground: return " + ytVideos.size());
    return ytVideos;
}

}

此代码在我的应用程序的调试版本上没有任何问题 关于控制台开发者 youtube api 我将其设置为 none

当我更改我的应用程序以发布 Youtube 搜索代码时,任何方式都不起作用,我收到此错误

    {
  "error": {
    "code": 403,
    "message": "The request is missing a valid API key.",
    "errors": [
      {
        "message": "The request is missing a valid API key.",
        "domain": "global",
        "reason": "forbidden"
      }
    ],
    "status": "PERMISSION_DENIED"
  }
 }

我看看我的 api 有效

try and catch 错误中我得到了 http url 及其

https://www.googleapis.com/youtube/v3/search?p=pageInfo,nextPageToken,items(id/videoId,snippet/title,snippet/thumbnails/default/url)&q=WWWWWWCuoKigBEzKx-a1NowWWWJFNEvMAZtd0GM&r=id,snippet&s=50&u=D8%AA%D9%&v=video&hl=en

WWWWWWCuoKigBEzKx-a1NowWWWJFNEvMAZtd0GM 是我的 api 密钥,为了安全起见,我几乎没有改动

据我所知,key=

没有参数

一样 url 我将 q= 更改为 key= 并在浏览器中打开相同的 url,我得到了响应

所以我加

 searchList.set("key",Config.YOUTUBE_API_KEY);

我的代码,但在发布版本 List<Video> videoResults = resp.getItems(); 中的结果仍然为空

我确实搜索了一天,但我没有找到导致此问题的原因,为什么它在调试和发布时无法正常工作

有什么想法吗?

1 天后我找到了解决方案,在发布版本中更改了参数名称

api 必须有参数 Key= 但发布版本将其更改为 q= 并更改其他参数名称

所以我发现它启用了 Proguard 添加 useProguard true

在gradle中像这样

  buildTypes {
    release {
        
        minifyEnabled true
        useProguard true

        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.release
    }
}

然后在 proguard-rules.pro 添加这行

-keep class com.google.api.** { *; }

如果您在另一个包上遇到问题,您可以将 com.google.api.** 更改为另一个包名称

我也添加了这行

-keepparameternames
-ignorewarnings