Search code examples
javaandroidyoutubeandroid-asynctaskandroid-youtube-api

Android YouTube API Demo Load Videos using AsyncTask


got the code from https://github.com/youtube/yt-android-player

Modified the VideoListDemoActivity.java to load video list dynamically using JSON in AsyncTask:

/*
* Copyright 2012 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.examples.youtubeapidemo;

import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;

import com.google.android.youtube.player.YouTubeInitializationResult;
import com.google.android.youtube.player.YouTubePlayer;
import com.google.android.youtube.player.YouTubePlayer.OnFullscreenListener;
import com.google.android.youtube.player.YouTubePlayer.OnInitializedListener;
import com.google.android.youtube.player.YouTubePlayer.Provider;
import com.google.android.youtube.player.YouTubePlayerFragment;
import com.google.android.youtube.player.YouTubeThumbnailLoader;
import com.google.android.youtube.player.YouTubeThumbnailLoader.ErrorReason;
import com.google.android.youtube.player.YouTubeThumbnailView;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ListFragment;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.res.Configuration;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import android.widget.ListView;
import android.widget.TextView;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
* A sample Activity showing how to manage multiple YouTubeThumbnailViews in an adapter for display
* in a List. When the list items are clicked, the video is played by using a YouTubePlayerFragment.
* <p>
* The demo supports custom fullscreen and transitioning between portrait and landscape without
* rebuffering.
*/
@TargetApi(13)
public final class VideoListDemoActivity extends Activity implements OnFullscreenListener {

/** The duration of the animation sliding up the video in portrait. */
private static final int ANIMATION_DURATION_MILLIS = 300;
/** The padding between the video list and the video in landscape orientation. */
private static final int LANDSCAPE_VIDEO_PADDING_DP = 5;

private VideoListFragment listFragment;
private VideoFragment videoFragment;

private View videoBox;
private View closeButton;

private boolean isFullscreen;


/*
* 
* new code
* 
*/

private static String url = "http://gdata.youtube.com/feeds/api/users/DayAndNightNewsChd/uploads?v=2&alt=jsonc";
public static List<VideoEntry> VIDEO_LIST;
public static List<VideoEntry> list = new ArrayList<VideoEntry>();  



@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);


  /*
   * 
   * execute asynctask to get the video list
   * 
   */
  new JSONParse().execute();



}


/*
* 
* AsyncTask 
* 
*/


private class JSONParse extends AsyncTask<Void, Void, Void> 
{
  private ProgressDialog pDialog;
 @Override
 protected void onPreExecute() {
     super.onPreExecute();
     pDialog = new ProgressDialog(VideoListDemoActivity.this);
     pDialog.setMessage("Getting Data ...");
     pDialog.setIndeterminate(false);
     pDialog.setCancelable(false);
     pDialog.show();
 }
 @Override
 protected Void doInBackground(Void... arg0) {

     /*
      * 
      * 
      * get the data from server and load it into the array
      * 
      * 
      */
     try {

         HttpClient client = new DefaultHttpClient();

         HttpUriRequest request = new HttpGet(url);

         HttpResponse response = client.execute(request);

         String jsonString = StreamUtils.convertToString(response.getEntity().getContent());

         JSONObject json = new JSONObject(jsonString);
         JSONArray jsonArray = json.getJSONObject("data").getJSONArray("items");


         for (int i = 0; i < jsonArray.length(); i++) {
             JSONObject jsonObject = jsonArray.getJSONObject(i);

             String title = jsonObject.getString("title");
             String video = jsonObject.getString("id");
             Log.d("YOUTUBE", title);
             list.add(new VideoEntry(title, video));
         }

     } catch (ClientProtocolException e) {
         //Log.e("Feck", e);
     } catch (IOException e) {
         //Log.e("Feck", e);
     } catch (JSONException e) {
         //Log.e("Feck", e);
     }

     VIDEO_LIST = Collections.unmodifiableList(list);




     return null;         
 }

 @Override
 protected void onPostExecute(Void result) {

        /*
         * 
         * 
         * this should be done in the oncreate() but causes app to crash
         *
         * 
         */

        setContentView(R.layout.video_list_demo);


        listFragment = (VideoListFragment) getFragmentManager().findFragmentById(R.id.list_fragment);
        videoFragment =
            (VideoFragment) getFragmentManager().findFragmentById(R.id.video_fragment_container);

        closeButton = findViewById(R.id.close_button);
        videoBox = findViewById(R.id.video_box);

        videoBox.setVisibility(View.INVISIBLE);

        layout();


        pDialog.dismiss();
  }
}//end async




@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);

layout();
}

@Override
public void onFullscreen(boolean isFullscreen) {
this.isFullscreen = isFullscreen;

layout();
}

/**
* Sets up the layout programatically for the three different states. Portrait, landscape or
* fullscreen+landscape. This has to be done programmatically because we handle the orientation
* changes ourselves in order to get fluent fullscreen transitions, so the xml layout resources
* do not get reloaded.
*/
private void layout() {
boolean isPortrait =
    getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;

listFragment.getView().setVisibility(isFullscreen ? View.GONE : View.VISIBLE);
listFragment.setLabelVisibility(isPortrait);
closeButton.setVisibility(isPortrait ? View.VISIBLE : View.GONE);

if (isFullscreen) {
  videoBox.setTranslationY(0); // Reset any translation that was applied in portrait.
  setLayoutSize(videoFragment.getView(), MATCH_PARENT, MATCH_PARENT);
  setLayoutSizeAndGravity(videoBox, MATCH_PARENT, MATCH_PARENT, Gravity.TOP | Gravity.LEFT);
} else if (isPortrait) {
  setLayoutSize(listFragment.getView(), MATCH_PARENT, MATCH_PARENT);
  setLayoutSize(videoFragment.getView(), MATCH_PARENT, WRAP_CONTENT);
  setLayoutSizeAndGravity(videoBox, MATCH_PARENT, WRAP_CONTENT, Gravity.BOTTOM);
} else {
  videoBox.setTranslationY(0); // Reset any translation that was applied in portrait.
  int screenWidth = dpToPx(getResources().getConfiguration().screenWidthDp);
  setLayoutSize(listFragment.getView(), screenWidth / 4, MATCH_PARENT);
  int videoWidth = screenWidth - screenWidth / 4 - dpToPx(LANDSCAPE_VIDEO_PADDING_DP);
  setLayoutSize(videoFragment.getView(), videoWidth, WRAP_CONTENT);
  setLayoutSizeAndGravity(videoBox, videoWidth, WRAP_CONTENT,
      Gravity.RIGHT | Gravity.CENTER_VERTICAL);
}
}

@SuppressLint("NewApi")
public void onClickClose(@SuppressWarnings("unused") View view) {
listFragment.getListView().clearChoices();
listFragment.getListView().requestLayout();
videoFragment.pause();
videoBox.animate()
    .translationYBy(videoBox.getHeight())
    .setDuration(ANIMATION_DURATION_MILLIS)
    .withEndAction(new Runnable() {
      @Override
      public void run() {
        videoBox.setVisibility(View.INVISIBLE);
      }
    });
}

/**
* A fragment that shows a static list of videos.
*/
public static final class VideoListFragment extends ListFragment {

  /*
private static final List<VideoEntry> VIDEO_LIST;
static {
  List<VideoEntry> list = new ArrayList<VideoEntry>();
  list.add(new VideoEntry("YouTube Collection", "Y_UmWdcTrrc"));
  list.add(new VideoEntry("GMail Tap", "1KhZKNZO8mQ"));
  list.add(new VideoEntry("Chrome Multitask", "UiLSiqyDf4Y"));
  list.add(new VideoEntry("Google Fiber", "re0VRK6ouwI"));
  list.add(new VideoEntry("Autocompleter", "blB_X38YSxQ"));
  list.add(new VideoEntry("GMail Motion", "Bu927_ul_X0"));
  list.add(new VideoEntry("Translate for Animals", "3I24bSteJpw"));
  VIDEO_LIST = Collections.unmodifiableList(list);
}
*/

private PageAdapter adapter;
private View videoBox;

@Override
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  //new JSONParse().execute();

  adapter = new PageAdapter(getActivity(), VIDEO_LIST);
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
  super.onActivityCreated(savedInstanceState);

  videoBox = getActivity().findViewById(R.id.video_box);
  getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
  setListAdapter(adapter);
}

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
  String videoId = VIDEO_LIST.get(position).videoId;

  VideoFragment videoFragment =
      (VideoFragment) getFragmentManager().findFragmentById(R.id.video_fragment_container);
  videoFragment.setVideoId(videoId);

  // The videoBox is INVISIBLE if no video was previously selected, so we need to show it now.
  if (videoBox.getVisibility() != View.VISIBLE) {
    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
      // Initially translate off the screen so that it can be animated in from below.
      videoBox.setTranslationY(videoBox.getHeight());
    }
    videoBox.setVisibility(View.VISIBLE);
  }

  // If the fragment is off the screen, we animate it in.
  if (videoBox.getTranslationY() > 0) {
    videoBox.animate().translationY(0).setDuration(ANIMATION_DURATION_MILLIS);
  }
}

@Override
public void onDestroyView() {
  super.onDestroyView();

  adapter.releaseLoaders();
}

public void setLabelVisibility(boolean visible) {
  adapter.setLabelVisibility(visible);
}

}

/**
* Adapter for the video list. Manages a set of YouTubeThumbnailViews, including initializing each
* of them only once and keeping track of the loader of each one. When the ListFragment gets
* destroyed it releases all the loaders.
*/
private static final class PageAdapter extends BaseAdapter {

private final List<VideoEntry> entries;
private final List<View> entryViews;
private final Map<YouTubeThumbnailView, YouTubeThumbnailLoader> thumbnailViewToLoaderMap;
private final LayoutInflater inflater;
private final ThumbnailListener thumbnailListener;

private boolean labelsVisible;

public PageAdapter(Context context, List<VideoEntry> entries) {
  this.entries = entries;

  entryViews = new ArrayList<View>();
  thumbnailViewToLoaderMap = new HashMap<YouTubeThumbnailView, YouTubeThumbnailLoader>();
  inflater = LayoutInflater.from(context);
  thumbnailListener = new ThumbnailListener();

  labelsVisible = true;
}

public void releaseLoaders() {
  for (YouTubeThumbnailLoader loader : thumbnailViewToLoaderMap.values()) {
    loader.release();
  }
}

public void setLabelVisibility(boolean visible) {
  labelsVisible = visible;
  for (View view : entryViews) {
    view.findViewById(R.id.text).setVisibility(visible ? View.VISIBLE : View.GONE);
  }
}

@Override
public int getCount() {
  return entries.size();
}

@Override
public VideoEntry getItem(int position) {
  return entries.get(position);
}

@Override
public long getItemId(int position) {
  return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
  View view = convertView;
  VideoEntry entry = entries.get(position);

  // There are three cases here
  if (view == null) {
    // 1) The view has not yet been created - we need to initialize the YouTubeThumbnailView.
    view = inflater.inflate(R.layout.video_list_item, parent, false);
    YouTubeThumbnailView thumbnail = (YouTubeThumbnailView) view.findViewById(R.id.thumbnail);
    thumbnail.setTag(entry.videoId);
    thumbnail.initialize(DeveloperKey.DEVELOPER_KEY, thumbnailListener);
  } else {
    YouTubeThumbnailView thumbnail = (YouTubeThumbnailView) view.findViewById(R.id.thumbnail);
    YouTubeThumbnailLoader loader = thumbnailViewToLoaderMap.get(thumbnail);
    if (loader == null) {
      // 2) The view is already created, and is currently being initialized. We store the
      //    current videoId in the tag.
      thumbnail.setTag(entry.videoId);
    } else {
      // 3) The view is already created and already initialized. Simply set the right videoId
      //    on the loader.
      thumbnail.setImageResource(R.drawable.loading_thumbnail);
      loader.setVideo(entry.videoId);
    }
  }
  TextView label = ((TextView) view.findViewById(R.id.text));
  label.setText(entry.text);
  label.setVisibility(labelsVisible ? View.VISIBLE : View.GONE);
  return view;
}

private final class ThumbnailListener implements
    YouTubeThumbnailView.OnInitializedListener,
    YouTubeThumbnailLoader.OnThumbnailLoadedListener {

  @Override
  public void onInitializationSuccess(
      YouTubeThumbnailView view, YouTubeThumbnailLoader loader) {
    loader.setOnThumbnailLoadedListener(this);
    thumbnailViewToLoaderMap.put(view, loader);
    view.setImageResource(R.drawable.loading_thumbnail);
    String videoId = (String) view.getTag();
    loader.setVideo(videoId);
  }

  @Override
  public void onInitializationFailure(
      YouTubeThumbnailView view, YouTubeInitializationResult loader) {
    view.setImageResource(R.drawable.no_thumbnail);
  }

  @Override
  public void onThumbnailLoaded(YouTubeThumbnailView view, String videoId) {
  }

  @Override
  public void onThumbnailError(YouTubeThumbnailView view, ErrorReason errorReason) {
    view.setImageResource(R.drawable.no_thumbnail);
  }
}

}

public static final class VideoFragment extends YouTubePlayerFragment
  implements OnInitializedListener {

private YouTubePlayer player;
private String videoId;

public static VideoFragment newInstance() {
  return new VideoFragment();
}

@Override
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  initialize(DeveloperKey.DEVELOPER_KEY, this);
}

@Override
public void onDestroy() {
  if (player != null) {
    player.release();
  }
  super.onDestroy();
}

public void setVideoId(String videoId) {
  if (videoId != null && !videoId.equals(this.videoId)) {
    this.videoId = videoId;
    if (player != null) {
      player.cueVideo(videoId);
    }
  }
}

public void pause() {
  if (player != null) {
    player.pause();
  }
}

@Override
public void onInitializationSuccess(Provider provider, YouTubePlayer player, boolean restored) {
  this.player = player;
  player.addFullscreenControlFlag(YouTubePlayer.FULLSCREEN_FLAG_CUSTOM_LAYOUT);
  player.setOnFullscreenListener((VideoListDemoActivity) getActivity());
  if (!restored && videoId != null) {
    player.cueVideo(videoId);
  }
}

@Override
public void onInitializationFailure(Provider provider, YouTubeInitializationResult result) {
  this.player = null;
}

}

private static final class VideoEntry {
private final String text;
private final String videoId;

public VideoEntry(String text, String videoId) {
  this.text = text;
  this.videoId = videoId;
}
}

// Utility methods for layouting.

private int dpToPx(int dp) {
return (int) (dp * getResources().getDisplayMetrics().density + 0.5f);
}

private static void setLayoutSize(View view, int width, int height) {
LayoutParams params = view.getLayoutParams();
params.width = width;
params.height = height;
view.setLayoutParams(params);
}

private static void setLayoutSizeAndGravity(View view, int width, int height, int gravity) {
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams();
params.width = width;
params.height = height;
params.gravity = gravity;
view.setLayoutParams(params);
}

}

everything works as expected until I tap one of the videos to watch and the app crashes:

12-25 10:14:27.418: D/AbsListView(13958): Get MotionRecognitionManager
12-25 10:14:27.608: D/libEGL(13958): loaded /system/lib/egl/libEGL_mali.so
12-25 10:14:27.633: D/libEGL(13958): loaded /system/lib/egl/libGLESv1_CM_mali.so
12-25 10:14:27.638: D/libEGL(13958): loaded /system/lib/egl/libGLESv2_mali.so
12-25 10:14:27.663: D/(13958): Device driver API match
12-25 10:14:27.663: D/(13958): Device driver API version: 10
12-25 10:14:27.663: D/(13958): User space API version: 10 
12-25 10:14:27.663: D/(13958): mali: REVISION=Linux-r2p4-02rel0 BUILD_DATE=Thu Oct 25 08:43:05 KST 2012 
12-25 10:14:27.723: D/OpenGLRenderer(13958): Enabling debug mode 0
12-25 10:14:31.478: W/ResourceType(13958): Failure getting entry for 0x010802c0 (t=7 e=704) in package 0 (error -75)
12-25 10:14:31.568: D/dalvikvm(13958): GC_CONCURRENT freed 118K, 13% free 9721K/11143K, paused 16ms+23ms, total 88ms
12-25 10:14:33.153: D/dalvikvm(13958): GC_CONCURRENT freed 241K, 14% free 9932K/11463K, paused 12ms+12ms, total 52ms
12-25 10:14:33.233: D/AbsListView(13958): Get MotionRecognitionManager
12-25 10:14:33.313: D/dalvikvm(13958): GC_CONCURRENT freed 480K, 16% free 9956K/11783K, paused 12ms+3ms, total 30ms
12-25 10:14:33.398: D/dalvikvm(13958): GC_FOR_ALLOC freed 61K, 16% free 9979K/11783K, paused 21ms, total 23ms
12-25 10:14:33.398: I/dalvikvm-heap(13958): Grow heap (frag case) to 11.140MB for 144160-byte allocation
12-25 10:14:33.413: D/dalvikvm(13958): GC_FOR_ALLOC freed 1K, 16% free 10118K/11975K, paused 13ms, total 13ms
12-25 10:14:33.538: E/SpannableStringBuilder(13958): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
12-25 10:14:33.538: E/SpannableStringBuilder(13958): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
12-25 10:14:34.078: D/dalvikvm(13958): GC_CONCURRENT freed 247K, 14% free 10372K/11975K, paused 12ms+4ms, total 35ms
12-25 10:14:34.223: D/dalvikvm(13958): GC_CONCURRENT freed 252K, 14% free 10629K/12231K, paused 13ms+13ms, total 59ms
12-25 10:14:34.333: W/dalvikvm(13958): Unable to resolve superclass of Lcom/google/android/apps/youtube/core/player/overlay/bm; (844)
12-25 10:14:34.333: W/dalvikvm(13958): Link of class 'Lcom/google/android/apps/youtube/core/player/overlay/bm;' failed
12-25 10:14:34.333: E/dalvikvm(13958): Could not find class 'com.google.android.apps.youtube.core.player.overlay.bm', referenced from method com.google.android.apps.youtube.core.player.overlay.SubtitlesPreferences.<init>
12-25 10:14:34.333: W/dalvikvm(13958): VFY: unable to resolve new-instance 3657 (Lcom/google/android/apps/youtube/core/player/overlay/bm;) in Lcom/google/android/apps/youtube/core/player/overlay/SubtitlesPreferences;
12-25 10:14:34.333: D/dalvikvm(13958): VFY: replacing opcode 0x22 at 0x0019
12-25 10:14:34.333: E/dalvikvm(13958): Could not find class 'android.view.accessibility.CaptioningManager', referenced from method com.google.android.apps.youtube.core.player.overlay.SubtitlesPreferences.c
12-25 10:14:34.333: W/dalvikvm(13958): VFY: unable to resolve check-cast 845 (Landroid/view/accessibility/CaptioningManager;) in Lcom/google/android/apps/youtube/core/player/overlay/SubtitlesPreferences;
12-25 10:14:34.333: D/dalvikvm(13958): VFY: replacing opcode 0x1f at 0x000c
12-25 10:14:34.333: W/dalvikvm(13958): VFY: unable to find class referenced in signature (Landroid/view/accessibility/CaptioningManager;)
12-25 10:14:34.338: W/dalvikvm(13958): VFY: unable to find class referenced in signature (Landroid/view/accessibility/CaptioningManager;)
12-25 10:14:34.338: I/dalvikvm(13958): Could not find method android.view.accessibility.CaptioningManager.getFontScale, referenced from method com.google.android.apps.youtube.core.player.overlay.SubtitlesPreferences.a
12-25 10:14:34.338: W/dalvikvm(13958): VFY: unable to resolve virtual method 5865: Landroid/view/accessibility/CaptioningManager;.getFontScale ()F
12-25 10:14:34.338: D/dalvikvm(13958): VFY: replacing opcode 0x6e at 0x000a
12-25 10:14:34.343: W/dalvikvm(13958): VFY: unable to find class referenced in signature (Landroid/view/accessibility/CaptioningManager;)
12-25 10:14:34.343: I/dalvikvm(13958): Could not find method android.view.accessibility.CaptioningManager.getUserStyle, referenced from method com.google.android.apps.youtube.core.player.overlay.SubtitlesPreferences.b
12-25 10:14:34.343: W/dalvikvm(13958): VFY: unable to resolve virtual method 5866: Landroid/view/accessibility/CaptioningManager;.getUserStyle ()Landroid/view/accessibility/CaptioningManager$CaptionStyle;
12-25 10:14:34.343: D/dalvikvm(13958): VFY: replacing opcode 0x6e at 0x000c
12-25 10:14:34.343: W/dalvikvm(13958): Unable to resolve superclass of Lcom/google/android/apps/youtube/core/player/overlay/bm; (844)
12-25 10:14:34.343: W/dalvikvm(13958): Link of class 'Lcom/google/android/apps/youtube/core/player/overlay/bm;' failed
12-25 10:14:34.343: D/dalvikvm(13958): DexOpt: unable to opt direct call 0x5b51 at 0x1c in Lcom/google/android/apps/youtube/core/player/overlay/SubtitlesPreferences;.<init>
12-25 10:14:34.343: W/dalvikvm(13958): VFY: unable to resolve instance field 1850
12-25 10:14:34.343: D/dalvikvm(13958): VFY: replacing opcode 0x52 at 0x0003
12-25 10:14:34.343: I/dalvikvm(13958): DexOpt: unable to optimize instance field ref 0x073b at 0x07 in Lcom/google/android/apps/youtube/core/model/SubtitlesStyle;.<init>
12-25 10:14:34.343: I/dalvikvm(13958): DexOpt: unable to optimize instance field ref 0x073c at 0x0b in Lcom/google/android/apps/youtube/core/model/SubtitlesStyle;.<init>
12-25 10:14:34.348: I/dalvikvm(13958): DexOpt: unable to optimize instance field ref 0x073d at 0x0f in Lcom/google/android/apps/youtube/core/model/SubtitlesStyle;.<init>
12-25 10:14:34.398: D/dalvikvm(13958): GC_CONCURRENT freed 154K, 12% free 10942K/12423K, paused 12ms+3ms, total 40ms
12-25 10:14:35.993: D/dalvikvm(13958): GC_FOR_ALLOC freed 235K, 14% free 10953K/12679K, paused 24ms, total 24ms
12-25 10:14:35.993: I/dalvikvm-heap(13958): Grow heap (frag case) to 12.201MB for 259216-byte allocation
12-25 10:14:36.013: D/dalvikvm(13958): GC_FOR_ALLOC freed 1K, 14% free 11204K/12935K, paused 21ms, total 21ms
12-25 10:14:36.053: D/dalvikvm(13958): GC_FOR_ALLOC freed 1K, 14% free 11204K/12935K, paused 20ms, total 20ms
12-25 10:14:36.053: I/dalvikvm-heap(13958): Grow heap (frag case) to 12.447MB for 259216-byte allocation
12-25 10:14:36.073: D/dalvikvm(13958): GC_FOR_ALLOC freed <1K, 14% free 11457K/13191K, paused 21ms, total 21ms
12-25 10:14:36.148: D/dalvikvm(13958): GC_FOR_ALLOC freed 1K, 13% free 11711K/13447K, paused 26ms, total 27ms
12-25 10:14:36.178: D/dalvikvm(13958): GC_FOR_ALLOC freed 1K, 13% free 11965K/13703K, paused 18ms, total 18ms
12-25 10:14:45.913: D/AndroidRuntime(13958): Shutting down VM
12-25 10:14:45.913: W/dalvikvm(13958): threadid=1: thread exiting with uncaught exception (group=0x418562a0)
12-25 10:14:45.928: E/AndroidRuntime(13958): FATAL EXCEPTION: main
12-25 10:14:45.928: E/AndroidRuntime(13958): java.lang.NullPointerException
12-25 10:14:45.928: E/AndroidRuntime(13958):    at com.examples.youtubeapidemo.VideoListDemoActivity$VideoListFragment.onListItemClick(VideoListDemoActivity.java:337)
12-25 10:14:45.928: E/AndroidRuntime(13958):    at android.app.ListFragment$2.onItemClick(ListFragment.java:160)
12-25 10:14:45.928: E/AndroidRuntime(13958):    at android.widget.AdapterView.performItemClick(AdapterView.java:301)
12-25 10:14:45.928: E/AndroidRuntime(13958):    at android.widget.AbsListView.performItemClick(AbsListView.java:1280)
12-25 10:14:45.928: E/AndroidRuntime(13958):    at android.widget.AbsListView$PerformClick.run(AbsListView.java:3071)
12-25 10:14:45.928: E/AndroidRuntime(13958):    at android.widget.AbsListView$1.run(AbsListView.java:3973)
12-25 10:14:45.928: E/AndroidRuntime(13958):    at android.os.Handler.handleCallback(Handler.java:615)
12-25 10:14:45.928: E/AndroidRuntime(13958):    at android.os.Handler.dispatchMessage(Handler.java:92)
12-25 10:14:45.928: E/AndroidRuntime(13958):    at android.os.Looper.loop(Looper.java:137)
12-25 10:14:45.928: E/AndroidRuntime(13958):    at android.app.ActivityThread.main(ActivityThread.java:4921)
12-25 10:14:45.928: E/AndroidRuntime(13958):    at java.lang.reflect.Method.invokeNative(Native Method)
12-25 10:14:45.928: E/AndroidRuntime(13958):    at java.lang.reflect.Method.invoke(Method.java:511)
12-25 10:14:45.928: E/AndroidRuntime(13958):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
12-25 10:14:45.928: E/AndroidRuntime(13958):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
12-25 10:14:45.928: E/AndroidRuntime(13958):    at dalvik.system.NativeStart.main(Native Method)
12-25 10:14:57.303: I/Process(13958): Sending signal. PID: 13958 SIG: 9

I am testing the app on Samsung Galaxy S3 (Android 4.1.2) with eclipse IDE on a Linux Slitaz.

Any guidance will be much appreciated.


Solution

  • heres then answer:

    need to get a return value from the AsyncTask and then execute the setContentView etc etc code in the onCreate method! stackoverflow is the best!

    /*
    * Copyright 2012 Google Inc. All Rights Reserved.
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
    *      http://www.apache.org/licenses/LICENSE-2.0
    *
    * Unless required by applicable law or agreed to in writing, software
    * distributed under the License is distributed on an "AS IS" BASIS,
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    * See the License for the specific language governing permissions and
    * limitations under the License.
    */
    package com.examples.youtubeapidemo;
    
    import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
    import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
    
    import com.google.android.youtube.player.YouTubeInitializationResult;
    import com.google.android.youtube.player.YouTubePlayer;
    import com.google.android.youtube.player.YouTubePlayer.OnFullscreenListener;
    import com.google.android.youtube.player.YouTubePlayer.OnInitializedListener;
    import com.google.android.youtube.player.YouTubePlayer.Provider;
    import com.google.android.youtube.player.YouTubePlayerFragment;
    import com.google.android.youtube.player.YouTubeThumbnailLoader;
    import com.google.android.youtube.player.YouTubeThumbnailLoader.ErrorReason;
    import com.google.android.youtube.player.YouTubeThumbnailView;
    
    import android.annotation.SuppressLint;
    import android.annotation.TargetApi;
    import android.app.Activity;
    import android.app.ListFragment;
    import android.app.ProgressDialog;
    import android.content.Context;
    import android.content.res.Configuration;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    import android.view.Gravity;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.ViewGroup.LayoutParams;
    import android.widget.BaseAdapter;
    import android.widget.FrameLayout;
    import android.widget.ListView;
    import android.widget.TextView;
    
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.ExecutionException;
    
    import org.apache.http.HttpResponse;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.HttpUriRequest;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.json.JSONArray;
    import org.json.JSONException;
    import org.json.JSONObject;
    
    /**
    * A sample Activity showing how to manage multiple YouTubeThumbnailViews in an adapter for display
    * in a List. When the list items are clicked, the video is played by using a YouTubePlayerFragment.
    * <p>
    * The demo supports custom fullscreen and transitioning between portrait and landscape without
    * rebuffering.
    */
    @TargetApi(13)
    public final class VideoListDemoActivity extends Activity implements OnFullscreenListener {
    
    /** The duration of the animation sliding up the video in portrait. */
    private static final int ANIMATION_DURATION_MILLIS = 300;
    /** The padding between the video list and the video in landscape orientation. */
    private static final int LANDSCAPE_VIDEO_PADDING_DP = 5;
    
    private VideoListFragment listFragment;
    private VideoFragment videoFragment;
    
    private View videoBox;
    private View closeButton;
    
    private boolean isFullscreen;
    
    
    /*
    * 
    * new code
    * 
    */
    
    private static String url = "http://gdata.youtube.com/feeds/api/users/DayAndNightNewsChd/uploads?v=2&alt=jsonc";
    public static List<VideoEntry> VIDEO_LIST;
    public static List<VideoEntry> list = new ArrayList<VideoEntry>();  
    
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
    
    
      /*
       * 
       * execute asynctask to get the video list
       * 
       */
      JSONParse myAsyncTask = new JSONParse();
    // This must be called on UI thread:
    myAsyncTask.execute();
    // Calling this will block UI thread execution:
    //ExecutionResult result = myAsyncTask.get();
    
      //new JSONParse().execute();
    
      try {
        if (myAsyncTask.get() == true)
          {
    
            setContentView(R.layout.video_list_demo);
    
    
            listFragment = (VideoListFragment) getFragmentManager().findFragmentById(R.id.list_fragment);
            videoFragment =
                (VideoFragment) getFragmentManager().findFragmentById(R.id.video_fragment_container);
    
            closeButton = findViewById(R.id.close_button);
            videoBox = findViewById(R.id.video_box);
    
            videoBox.setVisibility(View.INVISIBLE);
    
            layout();
    
    
    
          }
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (ExecutionException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    
    
    
    }
    
    
    /*
    * 
    * AsyncTask 
    * 
    */
    
    
    private class JSONParse extends AsyncTask<Void, Void, Boolean> 
    {
      private ProgressDialog pDialog;
     @Override
     protected void onPreExecute() {
         super.onPreExecute();
         pDialog = new ProgressDialog(VideoListDemoActivity.this);
         pDialog.setMessage("Getting Data ...");
         pDialog.setIndeterminate(false);
         pDialog.setCancelable(false);
         pDialog.show();
     }
     @Override
     protected Boolean doInBackground(Void... arg0) {
         boolean status = false;
         /*
          * 
          * 
          * get the data from server and load it into the array
          * 
          * 
          */
         try {
    
             HttpClient client = new DefaultHttpClient();
    
             HttpUriRequest request = new HttpGet(url);
    
             HttpResponse response = client.execute(request);
    
             String jsonString = StreamUtils.convertToString(response.getEntity().getContent());
    
             JSONObject json = new JSONObject(jsonString);
             JSONArray jsonArray = json.getJSONObject("data").getJSONArray("items");
    
    
             for (int i = 0; i < jsonArray.length(); i++) {
                 JSONObject jsonObject = jsonArray.getJSONObject(i);
    
                 String title = jsonObject.getString("title");
                 String video = jsonObject.getString("id");
                 //Log.d("YOUTUBE", title);
                 list.add(new VideoEntry(title, video));
             }
    
         } catch (ClientProtocolException e) {
             //Log.e("Feck", e);
         } catch (IOException e) {
             //Log.e("Feck", e);
         } catch (JSONException e) {
             //Log.e("Feck", e);
         }
    
         VIDEO_LIST = Collections.unmodifiableList(list);
         status = true;
    
    
    
    
         return status;           
     }
    
     @Override
     protected void onPostExecute(Boolean result) {
    
            /*
             * 
             * 
             * this should be done in the oncreate() but causes app to crash
             *
             * 
             */
    
    
    
            pDialog.dismiss();
      }
    }//end async
    
    
    
    
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    
    layout();
    }
    
    @Override
    public void onFullscreen(boolean isFullscreen) {
    this.isFullscreen = isFullscreen;
    
    layout();
    }
    
    /**
    * Sets up the layout programatically for the three different states. Portrait, landscape or
    * fullscreen+landscape. This has to be done programmatically because we handle the orientation
    * changes ourselves in order to get fluent fullscreen transitions, so the xml layout resources
    * do not get reloaded.
    */
    private void layout() {
    boolean isPortrait =
        getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
    
    listFragment.getView().setVisibility(isFullscreen ? View.GONE : View.VISIBLE);
    listFragment.setLabelVisibility(isPortrait);
    closeButton.setVisibility(isPortrait ? View.VISIBLE : View.GONE);
    
    if (isFullscreen) {
      videoBox.setTranslationY(0); // Reset any translation that was applied in portrait.
      setLayoutSize(videoFragment.getView(), MATCH_PARENT, MATCH_PARENT);
      setLayoutSizeAndGravity(videoBox, MATCH_PARENT, MATCH_PARENT, Gravity.TOP | Gravity.LEFT);
    } else if (isPortrait) {
      setLayoutSize(listFragment.getView(), MATCH_PARENT, MATCH_PARENT);
      setLayoutSize(videoFragment.getView(), MATCH_PARENT, WRAP_CONTENT);
      setLayoutSizeAndGravity(videoBox, MATCH_PARENT, WRAP_CONTENT, Gravity.BOTTOM);
    } else {
      videoBox.setTranslationY(0); // Reset any translation that was applied in portrait.
      int screenWidth = dpToPx(getResources().getConfiguration().screenWidthDp);
      setLayoutSize(listFragment.getView(), screenWidth / 4, MATCH_PARENT);
      int videoWidth = screenWidth - screenWidth / 4 - dpToPx(LANDSCAPE_VIDEO_PADDING_DP);
      setLayoutSize(videoFragment.getView(), videoWidth, WRAP_CONTENT);
      setLayoutSizeAndGravity(videoBox, videoWidth, WRAP_CONTENT,
          Gravity.RIGHT | Gravity.CENTER_VERTICAL);
    }
    }
    
    @SuppressLint("NewApi")
    public void onClickClose(@SuppressWarnings("unused") View view) {
    listFragment.getListView().clearChoices();
    listFragment.getListView().requestLayout();
    videoFragment.pause();
    videoBox.animate()
        .translationYBy(videoBox.getHeight())
        .setDuration(ANIMATION_DURATION_MILLIS)
        .withEndAction(new Runnable() {
          @Override
          public void run() {
            videoBox.setVisibility(View.INVISIBLE);
          }
        });
    }
    
    /**
    * A fragment that shows a static list of videos.
    */
    public static final class VideoListFragment extends ListFragment {
    
      /*
    private static final List<VideoEntry> VIDEO_LIST;
    static {
      List<VideoEntry> list = new ArrayList<VideoEntry>();
      list.add(new VideoEntry("YouTube Collection", "Y_UmWdcTrrc"));
      list.add(new VideoEntry("GMail Tap", "1KhZKNZO8mQ"));
      list.add(new VideoEntry("Chrome Multitask", "UiLSiqyDf4Y"));
      list.add(new VideoEntry("Google Fiber", "re0VRK6ouwI"));
      list.add(new VideoEntry("Autocompleter", "blB_X38YSxQ"));
      list.add(new VideoEntry("GMail Motion", "Bu927_ul_X0"));
      list.add(new VideoEntry("Translate for Animals", "3I24bSteJpw"));
      VIDEO_LIST = Collections.unmodifiableList(list);
    }
    */
    
    private PageAdapter adapter;
    private View videoBox;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
    
      //new JSONParse().execute();
    
      adapter = new PageAdapter(getActivity(), VIDEO_LIST);
    }
    
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
      super.onActivityCreated(savedInstanceState);
    
      videoBox = getActivity().findViewById(R.id.video_box);
      getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
      setListAdapter(adapter);
    }
    
    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
      String videoId = VIDEO_LIST.get(position).videoId;
    
      VideoFragment videoFragment =
          (VideoFragment) getFragmentManager().findFragmentById(R.id.video_fragment_container);
      videoFragment.setVideoId(videoId);
    
      // The videoBox is INVISIBLE if no video was previously selected, so we need to show it now.
      if (videoBox.getVisibility() != View.VISIBLE) {
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
          // Initially translate off the screen so that it can be animated in from below.
          videoBox.setTranslationY(videoBox.getHeight());
        }
        videoBox.setVisibility(View.VISIBLE);
      }
    
      // If the fragment is off the screen, we animate it in.
      if (videoBox.getTranslationY() > 0) {
        videoBox.animate().translationY(0).setDuration(ANIMATION_DURATION_MILLIS);
      }
    }
    
    @Override
    public void onDestroyView() {
      super.onDestroyView();
    
      adapter.releaseLoaders();
    }
    
    public void setLabelVisibility(boolean visible) {
      adapter.setLabelVisibility(visible);
    }
    
    }
    
    /**
    * Adapter for the video list. Manages a set of YouTubeThumbnailViews, including initializing each
    * of them only once and keeping track of the loader of each one. When the ListFragment gets
    * destroyed it releases all the loaders.
    */
    private static final class PageAdapter extends BaseAdapter {
    
    private final List<VideoEntry> entries;
    private final List<View> entryViews;
    private final Map<YouTubeThumbnailView, YouTubeThumbnailLoader> thumbnailViewToLoaderMap;
    private final LayoutInflater inflater;
    private final ThumbnailListener thumbnailListener;
    
    private boolean labelsVisible;
    
    public PageAdapter(Context context, List<VideoEntry> entries) {
      this.entries = entries;
    
      entryViews = new ArrayList<View>();
      thumbnailViewToLoaderMap = new HashMap<YouTubeThumbnailView, YouTubeThumbnailLoader>();
      inflater = LayoutInflater.from(context);
      thumbnailListener = new ThumbnailListener();
    
      labelsVisible = true;
    }
    
    public void releaseLoaders() {
      for (YouTubeThumbnailLoader loader : thumbnailViewToLoaderMap.values()) {
        loader.release();
      }
    }
    
    public void setLabelVisibility(boolean visible) {
      labelsVisible = visible;
      for (View view : entryViews) {
        view.findViewById(R.id.text).setVisibility(visible ? View.VISIBLE : View.GONE);
      }
    }
    
    @Override
    public int getCount() {
      return entries.size();
    }
    
    @Override
    public VideoEntry getItem(int position) {
      return entries.get(position);
    }
    
    @Override
    public long getItemId(int position) {
      return 0;
    }
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
      View view = convertView;
      VideoEntry entry = entries.get(position);
    
      // There are three cases here
      if (view == null) {
        // 1) The view has not yet been created - we need to initialize the YouTubeThumbnailView.
        view = inflater.inflate(R.layout.video_list_item, parent, false);
        YouTubeThumbnailView thumbnail = (YouTubeThumbnailView) view.findViewById(R.id.thumbnail);
        thumbnail.setTag(entry.videoId);
        thumbnail.initialize(DeveloperKey.DEVELOPER_KEY, thumbnailListener);
      } else {
        YouTubeThumbnailView thumbnail = (YouTubeThumbnailView) view.findViewById(R.id.thumbnail);
        YouTubeThumbnailLoader loader = thumbnailViewToLoaderMap.get(thumbnail);
        if (loader == null) {
          // 2) The view is already created, and is currently being initialized. We store the
          //    current videoId in the tag.
          thumbnail.setTag(entry.videoId);
        } else {
          // 3) The view is already created and already initialized. Simply set the right videoId
          //    on the loader.
          thumbnail.setImageResource(R.drawable.loading_thumbnail);
          loader.setVideo(entry.videoId);
        }
      }
      TextView label = ((TextView) view.findViewById(R.id.text));
      label.setText(entry.text);
      label.setVisibility(labelsVisible ? View.VISIBLE : View.GONE);
      return view;
    }
    
    private final class ThumbnailListener implements
        YouTubeThumbnailView.OnInitializedListener,
        YouTubeThumbnailLoader.OnThumbnailLoadedListener {
    
      @Override
      public void onInitializationSuccess(
          YouTubeThumbnailView view, YouTubeThumbnailLoader loader) {
        loader.setOnThumbnailLoadedListener(this);
        thumbnailViewToLoaderMap.put(view, loader);
        view.setImageResource(R.drawable.loading_thumbnail);
        String videoId = (String) view.getTag();
        loader.setVideo(videoId);
      }
    
      @Override
      public void onInitializationFailure(
          YouTubeThumbnailView view, YouTubeInitializationResult loader) {
        view.setImageResource(R.drawable.no_thumbnail);
      }
    
      @Override
      public void onThumbnailLoaded(YouTubeThumbnailView view, String videoId) {
      }
    
      @Override
      public void onThumbnailError(YouTubeThumbnailView view, ErrorReason errorReason) {
        view.setImageResource(R.drawable.no_thumbnail);
      }
    }
    
    }
    
    public static final class VideoFragment extends YouTubePlayerFragment
      implements OnInitializedListener {
    
    private YouTubePlayer player;
    private String videoId;
    
    public static VideoFragment newInstance() {
      return new VideoFragment();
    }
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
    
      initialize(DeveloperKey.DEVELOPER_KEY, this);
    }
    
    @Override
    public void onDestroy() {
      if (player != null) {
        player.release();
      }
      super.onDestroy();
    }
    
    public void setVideoId(String videoId) {
      if (videoId != null && !videoId.equals(this.videoId)) {
        this.videoId = videoId;
        if (player != null) {
          player.cueVideo(videoId);
        }
      }
    }
    
    public void pause() {
      if (player != null) {
        player.pause();
      }
    }
    
    @Override
    public void onInitializationSuccess(Provider provider, YouTubePlayer player, boolean restored) {
      this.player = player;
      player.addFullscreenControlFlag(YouTubePlayer.FULLSCREEN_FLAG_CUSTOM_LAYOUT);
      player.setOnFullscreenListener((VideoListDemoActivity) getActivity());
      if (!restored && videoId != null) {
        player.cueVideo(videoId);
      }
    }
    
    @Override
    public void onInitializationFailure(Provider provider, YouTubeInitializationResult result) {
      this.player = null;
    }
    
    }
    
    private static final class VideoEntry {
    private final String text;
    private final String videoId;
    
    public VideoEntry(String text, String videoId) {
      this.text = text;
      this.videoId = videoId;
    }
    }
    
    // Utility methods for layouting.
    
    private int dpToPx(int dp) {
    return (int) (dp * getResources().getDisplayMetrics().density + 0.5f);
    }
    
    private static void setLayoutSize(View view, int width, int height) {
    LayoutParams params = view.getLayoutParams();
    params.width = width;
    params.height = height;
    view.setLayoutParams(params);
    }
    
    private static void setLayoutSizeAndGravity(View view, int width, int height, int gravity) {
    FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams();
    params.width = width;
    params.height = height;
    params.gravity = gravity;
    view.setLayoutParams(params);
    }
    
    }