Reputation: 120
first let's start with my code i used for get list of videos depend on search query of the user
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;
}
}
this code work without any problem on debug version of my app about the console developer youtube api i set it for none
any way when i change my app to release the Youtube search code not work and i got this error
{
"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"
}
}
i take look to my api its valid
from the try and catch
error i got the http url and its
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
where the WWWWWWCuoKigBEzKx-a1NowWWWJFNEvMAZtd0GM
its my api key i changed little for security
as i see there is no parameter with key=
so same url i change the q=
to key=
and open same url in the browser and i got response
so i add
searchList.set("key",Config.YOUTUBE_API_KEY);
to my code but still got null on result in List<Video> videoResults = resp.getItems();
in release version
i do search for one day and i did't find what cause this problem why its work in debug and in release not
any idea?
Upvotes: 3
Views: 300
Reputation: 120
after 1 day i found the solution the parameter names changed in release version
the the api must have parameter with Key=
but the release version change it to q=
and change other parameters name
so the soultion as i found its enable Proguard
by add useProguard true
in gradle like this
buildTypes {
release {
minifyEnabled true
useProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
then in the proguard-rules.pro add this lines
-keep class com.google.api.** { *; }
you can change the com.google.api.**
with another package name if you got problem on another package
also i add this lines
-keepparameternames
-ignorewarnings
Upvotes: 3