6267


Volleyを使って､YouTubeの動画データを取得しようとしたのですが､取得できませんでした｡  
リクエストURL､データ取得用のメソッドとデータ取得部分は以下のとおりです｡  
`response`をLogで出力して見ましたが表示されませんでした｡ なので､リクエスト自体ができていないのだと考えられます｡
また､エラーはここで得られた､データを送った先の`BasaAdapter`を拡張したクラスで､取得したクラスを参照しようとした時に､`NullPointerException`が出ました｡
その`BaseAdapter`拡張クラスも以下に掲示します｡

**リクエストURL**

[code]

    "https://www.googleapis.com/youtube/v3/videos?part=id,snippet,contentDetails,statistics&id="
                + videoId + "&key=" + apiKey
    
[/code]

ブラウザでも試したのでURLに問題は無いはずです｡Log出力もできました｡

**動画情報取得メソッド:**

[code]

    private void videoRequest(String url){
        RequestSingleton.getInstance(getActivity().getApplicationContext()).addToRequestQueue(new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                final Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").create();
    
                //動画情報を変数に代入
                //表示されない｡
                Log.d("responce", response.toString());
                videoDetail = gson.fromJson(response.toString(), VideoDetail.class);
                videoItem = videoDetail.items.get(0);
    
                String channelRequestUrl = "https://www.googleapis.com/youtube/v3/channels?part=id,snippet,statistics&id="
                        + videoItem.snippet.channelId + "&key=" + apiKey;
                channelRequest(channelRequestUrl);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("tag", new String(error.networkResponse.data), error);
            }
        }));
    }
    
[/code]

**メソッド呼び出し部:**

[code]

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        if(getArguments()!=null){
            this.videoId = getArguments().getString(VIDEO_ID);
        }
    
        mQueue = RequestSingleton.getInstance(getActivity().getApplicationContext()).getRequestQueue();
        apiKey = DeveloperKey.API_KEY;
        //初期化処理
        suggestVideoList1 = new ArrayList<>();
        suggestVideoList2 = new ArrayList<>();
        videoDetail = new VideoDetail();
        videoItem = new VideoItems();
        suggestVideoDetail = new VideoDetail();
        suggestVideoSearchResult = new VideoSearchResult();
        chSearch = new ChannelSearchResult();
        chItem = new ChannelSearchItems();
    
    
        //再生動画の動画情報をリクエスト
        Log.d("videoId", videoId);
        String videoRequestUrl = "https://www.googleapis.com/youtube/v3/videos?part=id,snippet,contentDetails,statistics&id="
                + videoId + "&key=" + apiKey;
        Log.d("url", videoRequestUrl);
    
        //動画情報を取得
        videoRequest(videoRequestUrl);
    }
    
[/code]

**BaseAdapter拡張クラス(修正版の修正版)**

[code]

    public class InfoListAdapter extends BaseAdapter{
    private Context context;
    private LayoutInflater inflater;
    private VideoItems videoItems;
    private ChannelSearchItems channelItems;
    private List<VideoItems> videoItemsList;
    private NumberFormat nft;
    
    private int minusCount;
    
    private static final int TITLE_AND_DESCRIPTION = 0;
    private static final int CH_TITLE_AND_SUB = 1;
    private static final int SUGGESTION = 2;
    
    public InfoListAdapter(Context context, VideoItems object1, ChannelSearchItems object2,
                           List<VideoItems> object3){
        inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        this.context = context;
        this.videoItems = object1;
        this.channelItems = object2;
        this.nft = NumberFormat.getNumberInstance();
        this.videoItemsList = new ArrayList<>();
        for(int i=0; i<object3.size(); i++){
            this.videoItemsList.add(object3.get(i));
        }
        this.minusCount=4;
    }
    
    //各ViewHolder
    static class TitleAndDescriptionViewHolder{
        TextView title;
        TextView viewCount;
        TextView description;
        TextView category;
        TextView license;
        TextView good;
        TextView bad;
        ImageView indicator;
    }
    
    static class ChNameAndSubViewHolder{
        ImageView chIcon;
        TextView chTitle;
        TextView subCount;
    }
    
    static class SuggestionListViewHolder{
        ImageView thumbnail0;
        TextView duration0;
        TextView title0;
        TextView chName0;
        TextView viewCount0;
        ImageView thumbnail1;
        TextView duration1;
        TextView title1;
        TextView chName1;
        TextView viewCount1;
        ImageView thumbnail2;
        TextView duration2;
        TextView title2;
        TextView chName2;
        TextView viewCount2;
    }
    
    @Override
    public long getItemId(int position){
        return position;
    }
    
    @Override
    public Object getItem(int position){
        return position;
    }
    
    @Override
    public int getCount(){
        return 4;
    }
    
    @Override
    public int getViewTypeCount(){
        return 4;
    }
    
    @Override
    public int getItemViewType(int position){
        return position;
    }
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent){
        int viewType = getItemViewType(position);
        if(viewType==TITLE_AND_DESCRIPTION) {
            //動画の説明等
            TitleAndDescriptionViewHolder tAndDHolder = new TitleAndDescriptionViewHolder();
            if (convertView == null) {
                convertView = inflater.inflate(R.layout.title_and_description, parent, false);
                tAndDHolder.description = (TextView) convertView.findViewById(R.id.description);
                tAndDHolder.viewCount = (TextView) convertView.findViewById(R.id.view_count);
                tAndDHolder.title = (TextView) convertView.findViewById(R.id.video_title);
                tAndDHolder.category = (TextView) convertView.findViewById(R.id.category);
                tAndDHolder.license = (TextView) convertView.findViewById(R.id.license);
                tAndDHolder.good = (TextView) convertView.findViewById(R.id.good);
                tAndDHolder.bad = (TextView) convertView.findViewById(R.id.bad);
                tAndDHolder.indicator = (ImageView)convertView.findViewById(R.id.exp_button);
                convertView.setTag(tAndDHolder);
            } else {
                tAndDHolder = (TitleAndDescriptionViewHolder) convertView.getTag();
            }
    
            Picasso.with(context).load(android.R.drawable.arrow_down_float).into(tAndDHolder.indicator);
            tAndDHolder.title.setText(videoItems.snippet.title);
            tAndDHolder.description.setText(videoItems.snippet.description);
            tAndDHolder.viewCount.setText(nft.format(videoItems.statistics.viewCount) + " "
                    + R.string.views);
            tAndDHolder.category.setText(videoItems.snippet.categoryId);
            tAndDHolder.license.setText(videoItems.status.license);
            tAndDHolder.good.setText(nft.format(videoItems.statistics.likeCount));
            tAndDHolder.bad.setText(nft.format(videoItems.statistics.dislikeCount));
        }else if(viewType==CH_TITLE_AND_SUB) {
            //チャンネルタイトルと購読者数
            ChNameAndSubViewHolder cTAndSHolder = new ChNameAndSubViewHolder();
            if (convertView == null) {
                convertView = inflater.inflate(R.layout.ch_name_and_sub, parent, false);
                cTAndSHolder.chIcon = (ImageView) convertView.findViewById(R.id.ch_pic);
                cTAndSHolder.chTitle = (TextView) convertView.findViewById(R.id.ch_name);
                cTAndSHolder.subCount = (TextView) convertView.findViewById(R.id.sub_count);
                convertView.setTag(cTAndSHolder);
            } else {
                cTAndSHolder = (ChNameAndSubViewHolder) convertView.getTag();
            }
    
            Picasso.with(context).load(channelItems.snippet.thumbnails.default1.url)
                    .transform(new CircleTransform()).into(cTAndSHolder.chIcon);
            cTAndSHolder.subCount.setText(nft.format(channelItems.statistics.subscriberCount) + " "
                    + R.string.subs);
            cTAndSHolder.chTitle.setText(channelItems.snippet.title);
        }else if(viewType==SUGGESTION) {
            //おすすめという帯
            if (convertView == null) {
                convertView = inflater.inflate(R.layout.suggestion, parent, false);
            }
        }else{
            //おすすめ動画
            SuggestionListViewHolder suggestHolder = new SuggestionListViewHolder();
            if(convertView == null){
                //1列目
                convertView = inflater.inflate(R.layout.suggestion_list, parent,false);
                suggestHolder.chName0 = (TextView)convertView.findViewById(R.id.suggest_ch_name_0);
                suggestHolder.duration0 = (TextView)convertView.findViewById(R.id.suggest_duration0);
                suggestHolder.thumbnail0 = (ImageView)convertView.findViewById(R.id.iv_thumbnail_0);
                suggestHolder.title0 = (TextView)convertView.findViewById(R.id.suggest_video_name_0);
                suggestHolder.viewCount0 = (TextView)convertView.findViewById(R.id.suggest_video_view_0);
    
                //2列目
                suggestHolder.chName1 = (TextView)convertView.findViewById(R.id.suggest_ch_name_1);
                suggestHolder.duration1 = (TextView)convertView.findViewById(R.id.suggest_duration1);
                suggestHolder.thumbnail1 = (ImageView)convertView.findViewById(R.id.iv_thumbnail_1);
                suggestHolder.title1 = (TextView)convertView.findViewById(R.id.suggest_video_name_1);
                suggestHolder.viewCount1 = (TextView)convertView.findViewById(R.id.suggest_video_view_1);
    
                //3列目
                suggestHolder.chName2 = (TextView)convertView.findViewById(R.id.suggest_ch_name_2);
                suggestHolder.duration2 = (TextView)convertView.findViewById(R.id.suggest_duration2);
                suggestHolder.thumbnail2 = (ImageView)convertView.findViewById(R.id.iv_thumbnail_2);
                suggestHolder.title2 = (TextView)convertView.findViewById(R.id.suggest_video_name_2);
                suggestHolder.viewCount2 = (TextView)convertView.findViewById(R.id.suggest_video_view_2);
                convertView.setTag(suggestHolder);
            }else{
                suggestHolder = (SuggestionListViewHolder)convertView.getTag();
            }
    
            //1列目
            suggestHolder.chName0.setText(videoItemsList.get(position-minusCount).snippet.channelTitle);
            suggestHolder.duration0.setText(durationConverter(videoItemsList.get(position-minusCount).contentDetails.duration));
            Picasso.with(context).load(videoItemsList.get(position-minusCount).snippet.thumbnails.medium.url)
                    .placeholder(R.drawable.thumback).error(android.R.drawable.ic_dialog_alert)
                    .into(suggestHolder.thumbnail0);
            suggestHolder.title0.setText(videoItemsList.get(position-minusCount).snippet.title);
            suggestHolder.viewCount0.setText(nft.format(videoItemsList.get(position-minusCount).statistics.viewCount) + " " + R.string.views);
    
            //2列目
            suggestHolder.chName1.setText(videoItemsList.get(position-minusCount-1).snippet.channelTitle);
            suggestHolder.duration1.setText(durationConverter(videoItemsList.get(position-minusCount-1).contentDetails.duration));
            Picasso.with(context).load(videoItemsList.get(position-minusCount-1).snippet.thumbnails.medium.url)
                    .placeholder(R.drawable.thumback).error(android.R.drawable.ic_dialog_alert)
                    .into(suggestHolder.thumbnail1);
            suggestHolder.title1.setText(videoItemsList.get(position-minusCount-1).snippet.title);
            suggestHolder.viewCount1.setText(nft.format(videoItemsList.get(position-minusCount-1).statistics.viewCount) + " " + R.string.views);
    
            //3列目
            suggestHolder.chName2.setText(videoItemsList.get(position-minusCount-2).snippet.channelTitle);
            suggestHolder.duration2.setText(durationConverter(videoItemsList.get(position-minusCount-2).contentDetails.duration));
            Picasso.with(context).load(videoItemsList.get(position-minusCount-2).snippet.thumbnails.medium.url)
                    .placeholder(R.drawable.thumback).error(android.R.drawable.ic_dialog_alert)
                    .into(suggestHolder.thumbnail2);
            suggestHolder.title2.setText(videoItemsList.get(position-minusCount-2).snippet.title);
            suggestHolder.viewCount2.setText(nft.format(videoItemsList.get(position-minusCount-2).statistics.viewCount) + " " + R.string.views);
            minusCount--;
        }
        return convertView;
    }
    ..............................
    
[/code]

解決方法がありましたら｡どうぞよろしくおねがいします｡

**エラーログ**

[code]

    02-10 20:43:51.431  23372-23372/com.wotageishika.zousan.wotageishika E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.wotageishika.zousan.wotageishika, PID: 23372
    java.lang.NullPointerException: Attempt to read from field 'java.lang.String com.wotageishika.zousan.wotageishika.VideoSnippet.title' on a null object reference
            at com.wotageishika.zousan.wotageishika.InfoListAdapter.getView(InfoListAdapter.java:131)
            at android.widget.AbsListView.obtainView(AbsListView.java:2344)
            at android.widget.ListView.measureHeightOfChildren(ListView.java:1270)
            at android.widget.ListView.onMeasure(ListView.java:1182)
            at android.view.View.measure(View.java:17430)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
            at android.view.View.measure(View.java:17430)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
            at android.view.View.measure(View.java:17430)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
            at android.view.View.measure(View.java:17430)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
            at android.view.View.measure(View.java:17430)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
            at android.view.View.measure(View.java:17430)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
            at android.view.View.measure(View.java:17430)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5463)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:430)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2560)
            at android.view.View.measure(View.java:17430)
            at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2001)
            at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1166)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1372)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1054)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5779)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
            at android.view.Choreographer.doCallbacks(Choreographer.java:580)
            at android.view.Choreographer.doFrame(Choreographer.java:550)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
    
[/code]

**リクエストURLのログ出力:**

[code]

    D/url﹕ https://www.googleapis.com/youtube/v3/videos?part=id,snippet,contentDetails,statistics&id=at8Z3KQnb9Q&key=AIzaSyAw-Gp-yjGm2agxAVr08-k5hLxIfjitGiI
    
[/code]


CC BY-SA 3.0
2015-02-10T12:05:19.783
6266
2015-02-11T12:48:56.413
2015-02-11T12:48:56.413
7232
7232
question
android api youtube-data-api android-volley
Volleyでデータを取得できない｡


問題の箇所を見つけました。`Volley`関係ないです。

[code]

    @Override
    public View getView(int position, View convertView, ViewGroup parent){
        if(position==TITLE_AND_DESCRIPTION) {
            //動画の説明等
            TitleAndDescriptionViewHolder tAndDHolder = new TitleAndDescriptionViewHolder();
            if (convertView == null) {
                convertView = inflater.inflate(R.layout.title_and_description, parent, false);
                tAndDHolder.description = (TextView) convertView.findViewById(R.id.description);
                tAndDHolder.viewCount = (TextView) convertView.findViewById(R.id.view_count);
                tAndDHolder.title = (TextView) convertView.findViewById(R.id.video_title);
                tAndDHolder.category = (TextView) convertView.findViewById(R.id.category);
                tAndDHolder.license = (TextView) convertView.findViewById(R.id.license);
                tAndDHolder.good = (TextView) convertView.findViewById(R.id.good);
                tAndDHolder.bad = (TextView) convertView.findViewById(R.id.bad);
                tAndDHolder.indicator = (ImageView)convertView.findViewById(R.id.exp_button);
            } else {
                tAndDHolder = (TitleAndDescriptionViewHolder) convertView.getTag();
                // 多分これは毎回nullになる
            }
    
            Picasso.with(context).load(android.R.drawable.arrow_down_float).into(tAndDHolder.indicator);
            //ここでエラーがでる｡
            tAndDHolder.title.setText(videoItems.snippet.title);
    
[/code]

`getView()`の引数で渡される`convertView`ですが、`null`時の初回生成時に`setTag()`で`ViewHolder`をタグにいれるのを忘れています。なので、2回目以降の`getTag()`で`null`が返ってむるのが原因な気がします。


CC BY-SA 3.0
2015-02-10T12:48:52.207
6267
2015-02-10T12:48:52.207
845
6266
answer