2

私は Android 開発の初心者であり、Onur Cinar による書籍「Android Apps with Eclipse」を使用して開始しています。

MoviePlayer アプリ (ソース コード: http://www.apress.com/9781430244349 ) を開発する第 6 章を完了しましたが、携帯電話でアプリを実行すると、一覧表示された映画のサムネイルが表示されません。携帯電話を使用して新しい映画を録画すると、新しい映画が映画リストに追加され、デフォルトの緑色の Android アイコンがサムネイルとして表示され、元の映画にはまだサムネイル アイコンがありません。

私のコードは、指定されたソース コードのコードと一致しているようです。本に記載されているコードに何か問題がありますか、それともこれは予想される動作ですか? 後者の場合、どのような状況で (デフォルトではない) サムネイル アイコンがムービー リストに表示されますか?

ムービー.java:

package com.apress.movieplayer;

import android.database.Cursor;
import android.provider.MediaStore;

/**
 * Movie file meta data.
 * 
 * @author Josh
 */
public class Movie
{
/** Movie title */
private final String title;

/** Movie file */
private final String moviePath;

/** MIME type */
private final String mimeType;

/** Movie duration in ms */
private final long duration;

/** Thumbnail file */
private final String thumbnailPath;

/**
 * Constructor.
 * 
 * @param mediaCursor media cursor.
 * @param thumbnailCursor thumbnail cursor.
 */
public Movie(Cursor mediaCursor, Cursor thumbnailCursor)
{
    title = mediaCursor.getString(mediaCursor.getColumnIndexOrThrow(
            MediaStore.Video.Media.TITLE));

    moviePath = mediaCursor.getString(mediaCursor.getColumnIndex(
            MediaStore.Video.Media.DATA));

    mimeType = mediaCursor.getString(mediaCursor.getColumnIndex(
            MediaStore.Video.Media.MIME_TYPE));

    duration = mediaCursor.getLong(mediaCursor.getColumnIndex(
            MediaStore.Video.Media.DURATION));

    if ( (thumbnailCursor != null) && thumbnailCursor.moveToFirst() )
    {
        thumbnailPath = thumbnailCursor.getString(
                thumbnailCursor.getColumnIndex(
                        MediaStore.Video.Thumbnails.DATA));
    }
    else
    {
        thumbnailPath = null;
    }
}

/**
 * Get the movie title.
 * 
 * @return movie title.
 */
public String getTitle() {
    return title;
}

/**
 * Get the movie path.
 * 
 * @return movie path.
 */
public String getMoviePath() {
    return moviePath;
}

/**
 * Get the MIME type.
 * 
 * @return MIME type.
 */
public String getMimeType() {
    return mimeType;
}

/**
 * Get the movie duration.
 * 
 * @return movie duration.
 */
public long getDuration() {
    return duration;
}

/**
 * Get the thumbnail path.
 * 
 * @return thumbnail path.
 */
public String getThumbnailPath() {
    return thumbnailPath;
}

/*
 * @see java.lang.Object#toString()
 */
@Override
public String toString()
{
    return "Movie [title=" + title + ", moviePath=" + moviePath
            + ", mimeType=" + mimeType + ", duration=" + duration
            + ", thumbnailPath=" + thumbnailPath + "]";
}
}

MovieListAdapter.java:

package com.apress.movieplayer;

import java.util.ArrayList;

import android.content.Context;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * Movie list view adapter.
 * 
 * @author Josh
 */
public class MovieListAdapter extends BaseAdapter
{
/** Context instance */
private final Context context;

/** Movie list */
private final ArrayList<Movie> movieList;

/**
 * Constructor.
 * 
 * @param context context instance.
 * @param movieList movie list.
 */
public MovieListAdapter(Context context, ArrayList<Movie> movieList)
{
    this.context = context;
    this.movieList = movieList;
}

/**
 * Gets the number of elements in movie list.
 * 
 * @see BaseAdapter#getCount()
 */
public int getCount() {
    return movieList.size();
}

/**
 * Gets the movie item at given position.
 * 
 * @param position item position.
 * @see BaseAdapter#getItem(int)
 */
public Object getItem(int position) {
    return movieList.get(position);
}

/**
 * Gets the movie id at given position.
 * 
 * @param position item position.
 * @return movie id.
 * @see BaseAdapter#getItemId(int)
 */
public long getItemId(int position) {
    return position;
}

/**
 * Gets the item view for given position.
 * 
 * @param position item position.
 * @param convertView existing view to use.
 * @param parent parent view to use.
 */
public View getView(int position, View convertView, ViewGroup parent) {
    // check if convert view exists or inflate the layout
    if (convertView == null)
    {
        LayoutInflater layoutInflater = (LayoutInflater)
                context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = layoutInflater.inflate(R.layout.movie_item, null);
    }

    // Get the movie at given position
    Movie movie = (Movie) getItem(position);

    // Set thumbnail
    ImageView thumbnail = (ImageView) convertView.findViewById(
            R.id.thumbnail);

    if (movie.getThumbnailPath() != null)
    {
        thumbnail.setImageURI(Uri.parse(movie.getThumbnailPath()));
    }
    else
    {
        thumbnail.setImageResource(R.drawable.ic_launcher);
    }

    // Set title
    TextView title = (TextView) convertView.findViewById(R.id.title);
    title.setText(movie.getTitle());

    // Set duration
    TextView duration = (TextView) convertView.findViewById(R.id.duration);
    duration.setText(getDurationAsString(movie.getDuration()));

    return convertView;
}

private static String getDurationAsString(long duration)
{
    // Calculate milliseconds
    long milliseconds = duration % 1000;
    long seconds = duration / 1000;

    // Calculate seconds
    long minutes = seconds / 60;
    seconds %= 60;

    // Calculate hours and minutes
    long hours = minutes / 60;
    minutes %= 60;

    // Build the duration string
    String durationString = String.format("%1$02d:%2$02d:%3$02d.%4$03d",
            hours, minutes, seconds, milliseconds);

    return durationString;
}

}

MoviePlayerActivity.java:

package com.apress.movieplayer;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
//import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;

/**
 * Movie Player.
 * 
 * @author Josh
 *
 */
public class MoviePlayerActivity extends Activity implements OnItemClickListener
{
/** Log tag. */
private static final String LOG_TAG = "MoviePlayer";


/**
 * On create lifecycle method.
 * 
 * @param savedInstanceState saved state.
 * @see Activity#onCreate(Bundle)
 */
@Override
    protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_movie_player);

    ArrayList<Movie> movieList = new ArrayList<Movie>();

    // Media columns to query
    String[] mediaColumns = {
            MediaStore.Video.Media._ID,
            MediaStore.Video.Media.TITLE,
            MediaStore.Video.Media.DURATION,
            MediaStore.Video.Media.DATA,
            MediaStore.Video.Media.MIME_TYPE };

    // Thumbnail columns to query
    String[] thumbnailColumns = { MediaStore.Video.Thumbnails.DATA };

    // Query external movie content for selected media columns
    Cursor mediaCursor = getContentResolver().query(
            MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
            mediaColumns, null, null, null);

            /*managedQuery(
            MediaStore.Video.Media.EXTERNAL_CONTENT_URI, mediaColumns,
            null, null, null);*/

    // Loop through media results
    if ( (mediaCursor != null) && mediaCursor.moveToFirst() )
    {
        do
        {
            // Get the video id
            int id = mediaCursor.getInt(mediaCursor
                    .getColumnIndex(MediaStore.Video.Media._ID));

            // Get the thumbnail associated with the video
            Cursor thumbnailCursor = getContentResolver().query(
                    MediaStore.Video.Thumbnails.EXTERNAL_CONTENT_URI,
                    thumbnailColumns, MediaStore.Video.Thumbnails.VIDEO_ID
                        + "=" + id, null, null);

                    /*managedQuery(
                    MediaStore.Video.Thumbnails.EXTERNAL_CONTENT_URI,
                    thumbnailColumns, MediaStore.Video.Thumbnails.VIDEO_ID
                            + "=" + id, null, null);*/

            // New movie object from the data
            Movie movie = new Movie(mediaCursor, thumbnailCursor);
            Log.d(LOG_TAG, movie.toString());

            // Add to movie list
            movieList.add(movie);

        }
        while (mediaCursor.moveToNext());
    }

    // Define movie list adapter
    MovieListAdapter movieListAdapter = new MovieListAdapter(this,
            movieList);

    // Set list view adapter to movie list adapter
    ListView movieListView = (ListView) findViewById(R.id.movieListView);
    movieListView.setAdapter(movieListAdapter);

    // Set  item click listener
    movieListView.setOnItemClickListener(this);
}

@Override
/*public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.activity_movie_player, menu);
    return true;
}*/

    /**
     * On item click listener.
     */
    public void onItemClick(AdapterView<?> parent, View view, int position, long id)
    {
        // Gets the selected movie
        Movie movie = (Movie) parent.getAdapter().getItem(position);

        // Plays the selected movie
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.parse(movie.getMoviePath()), movie.getMimeType());
        startActivity(intent);
    }
}

activity_movie_player.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <ListView
        android:id="@+id/movieListView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
    </ListView>
</LinearLayout>

movie_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

<ImageView
    android:contentDescription="@string/thumbnail_description"
    android:id="@+id/thumbnail"
    android:layout_width="64dp"
    android:layout_height="64dp"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:layout_marginRight="16dp"
    android:src="@drawable/ic_launcher" />
<TextView
    android:id="@+id/title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignTop="@+id/thumbnail"
    android:layout_toRightOf="@+id/thumbnail"
    android:text="@string/large_text"
    android:textAppearance="?android:attr/textAppearanceLarge" />

<TextView 
    android:id="@+id/duration"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/title"
    android:layout_below="@+id/title"
    android:text="@string/small_text"
    android:textAppearance="?android:attr/textAppearanceSmall" />

</RelativeLayout>
4

1 に答える 1

0

コードを見ると、これは Android OS の通常の機能のようです。ビデオが他のビデオ再生アプリケーションによって開かれると、これらのより高度なプログラム内でサムネイルが生成され、他のアプリケーション (このデモ ムービー プレーヤー アプリを含む) で利用できるようになります。

私の分析はややブラックボックスであるため、これが実際に「舞台裏」でどのように機能するかについて誰かが詳しく説明していただければ幸いです。

于 2012-12-14T21:52:58.883 に答える