从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)上的应用程序。
非常感谢任何指导。
答案 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);
}
}