Android YouTube API演示使用AsyncTask加载视频

时间:2013-12-24 23:22:16

标签: java android youtube android-asynctask android-youtube-api

https://github.com/youtube/yt-android-player

获取代码

修改VideoListDemoActivity.java以使用AsyncTask中的JSON动态加载视频列表:

/*
* 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);
}

}

一切都按预期工作,直到我点击其中一个视频观看并且应用崩溃:

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

我正在使用Linux Slitaz上的eclipse IDE测试Samsung Galaxy S3(Android 4.1.2)上的应用程序。

非常感谢任何指导。

1 个答案:

答案 0 :(得分:1)

然后接下来回答:

需要从AsyncTask获取返回值,然后在onCreate方法中执行setContentView等代码! stackoverflow是最好的!

/*
* 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);
}

}