この記事では,大きく3つのことを行います.
- Youtubeから「共有」をした際の一覧に自分のアプリを登録する.
- 「共有」した際のリンク情報から,IDを取得し,そのIDからYoutubeの動画情報を取得する.
- Retrofit & GsonでAPIにアクセス.動画情報を取得アプリ上に表示する.
コードは,ここにおいてます.SharedText
1. Youtubeから「共有」をした際の一覧に自分のアプリを登録する.
まず,Manifest.xmlにintent-filterを追加します.
// ... 中略 ...
<activity android:name=".SharedActivity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain"/>
</intent-filter>
</activity>
// ... 中略 ...
次にSharedActivity.javaで受け取ってみる.
public class SharedActivity extends AppCompatActivity {
TextView textView;
ImageView thumbnail;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shared);
textView = findViewById(R.id.movieId);
thumbnail = findViewById(R.id.thumbnail);
Intent intent = getIntent();
String id = null;
if(intent.getType().equals("text/plain")){
String text = intent.getStringExtra(Intent.EXTRA_TEXT);
Log.d("text",text);
}
}
// ... 中略 ...
}
これでtextにIntentで渡ってきたリンクを受け取ることができます.
[参考]
* データのシェア - 他のプログラムからのデータを受け取る
* # 暗黙的インテントを受け取る(ドキュメント)
2. 「共有」した際のリンク情報から,IDを取得し,そのIDからYoutubeの動画情報を取得する.
IDの取得方法
これは素直にリンクの文字列からIDを抜き出しました.
https://youtu.be/yT_ylSCgY6Q
という感じで文字列が取得できるので,後ろのyT_ylSCgY6Q
が動画のID.
ちなみに,上のリンクでは,BUMP OF CHICKEN feat. HATSUNE MIKU「ray」に飛びます.
Youtubeの動画情報を取得する.
YouTubeの動画情報をData API v3を使って取得するの記事のように,Youtubeの動画の情報を取得するには,Youtube Data API を用います.
API keyを取得して,以下のURLをブラウザで入力してください.API Keyの取得については,YouTubeの動画情報をData API v3を使って取得する を参照してください.
https://www.googleapis.com/youtube/v3/videos?id=yT_ylSCgY6Q&key=【API Key】&fields=items(id,snippet(channelTitle,title,thumbnails),statistics)&part=snippet,contentDetails,statistics
【API Key】の部分に,取得したkeyを入力してください.
結果としては,以下のように得られます.
{
"items": [
{
"id": "yT_ylSCgY6Q",
"snippet": {
"title": "BUMP OF CHICKEN feat. HATSUNE MIKU「ray」",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/yT_ylSCgY6Q/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https://i.ytimg.com/vi/yT_ylSCgY6Q/mqdefault.jpg",
"width": 320,
"height": 180
},
"high": {
"url": "https://i.ytimg.com/vi/yT_ylSCgY6Q/hqdefault.jpg",
"width": 480,
"height": 360
},
"standard": {
"url": "https://i.ytimg.com/vi/yT_ylSCgY6Q/sddefault.jpg",
"width": 640,
"height": 480
},
"maxres": {
"url": "https://i.ytimg.com/vi/yT_ylSCgY6Q/maxresdefault.jpg",
"width": 1280,
"height": 720
}
},
"channelTitle": "BUMP OF CHICKEN"
},
"statistics": {
"viewCount": "12691874",
"likeCount": "65136",
"dislikeCount": "3062",
"favoriteCount": "0",
"commentCount": "4337"
}
}
]
}
[参考]
* YouTubeの動画情報をData API v3を使って取得する
3. Retrofit & GsonでAPIにアクセス.動画情報を取得アプリ上に表示する.
概要
- Retrofit: Android の HTTP クライアントライブラリ
- Gson: JSON を Java のオブジェクトに変換するライブラリ
導入
- build.gradle (Module: app) に追加
dependencies {
// ... 中略 ...
implementation 'com.google.code.gson:gson:2.8.4'
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
// ... 中略 ...
}
APIのインタフェースの実装
public interface ApiService {
@Headers("Accept-Language: ja")
@GET("/youtube/v3/videos?")
Call<APIResponse> requestMovie(@Query("id") String id,
@Query("key") String key,
@Query("fields") String fields,
@Query("part") String part);
}
API から取得したデータを Java オブジェクトとして格納するクラスを定義
public class APIResponse {
public List<Item> items;
public List<Item> getItems() {
return items;
}
}
public class Item {
@SerializedName("id")
private String id;
@SerializedName("snippet")
private Snippet snippet;
@SerializedName("statistics")
private Statistics statistics;
public String getId() {
return id;
}
public Snippet getSnippet() {
return snippet;
}
public Statistics getStatistics() {
return statistics;
}
}
public class Snippet {
@SerializedName("title")
private String title;
@SerializedName("thumbnails")
private Thumbnails thumbnails;
public class Thumbnails {
@SerializedName("default")
public Default aDefault;
@SerializedName("medium")
public Medium medium;
@SerializedName("high")
public High high;
public High getHigh() {
return high;
}
@SerializedName("standard")
public Standard standard;
@SerializedName("maxres")
public Maxres maxres;
public class Default {
String url;
String width;
String height;
}
public class Medium {
String url;
String width;
String height;
}
public class High {
String url;
String width;
String height;
public String getUrl() {
return url;
}
}
public class Standard {
String url;
String width;
String height;
}
public class Maxres {
String url;
String width;
String height;
}
}
@SerializedName("channelTitle")
String channelTitle;
public String getTitle() {
return title;
}
public Thumbnails getThumbnails() {
return thumbnails;
}
public String getChannelTitle() {
return channelTitle;
}
}
public class Statistics {
@SerializedName("viewCount")
String viewCount;
@SerializedName("likeCount")
String likeCount;
@SerializedName("dislikeCount")
String dislikeCount;
@SerializedName("favoriteCount")
String favoriteCount;
@SerializedName("commentCount")
String commentCount;
public String getViewCount() {
return viewCount;
}
public String getLikeCount() {
return likeCount;
}
public String getDislikeCount() {
return dislikeCount;
}
public String getFavoriteCount() {
return favoriteCount;
}
public String getCommentCount() {
return commentCount;
}
}
記事を書いていて,修飾子まわりをあまり考えずに書いてしまっていたことに気づいたので,そのあたりはよしなにしていただけると嬉しいです.
YouTube Data API v3にアクセスし、動画の情報を取得するための処理の実装
public class MainActivity extends AppCompatActivity {
private Retrofit mRetrofit;
private ApiService mService;
// API KEY 各自Consoleから作成
private final String API_KEY = "dummyAPIKey"; // 適宜APIKeyを変えてください.
private final String FIELDS = "items(id,snippet(channelTitle,title,thumbnails),statistics)";
private final String PART = "snippet,contentDetails,statistics";
// "BUMP OF CHICKEN feat. HATSUNE MIKU「ray」"
private String testId = "yT_ylSCgY6Q";
ImageView picture;
TextView title;
Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRetrofit = new Retrofit.Builder()
.baseUrl("https://www.googleapis.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
mService = mRetrofit.create(ApiService.class);
picture = findViewById(R.id.picture);
title = findViewById(R.id.title);
button = findViewById(R.id.button);
button.setOnClickListener(onClickListener);
}
private View.OnClickListener onClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
Call<APIResponse> mCall = mService.requestMovie(testId,API_KEY,FIELDS,PART);
mCall.enqueue(new Callback<APIResponse>() {
@Override
public void onResponse(Call<APIResponse> call, Response<APIResponse> response) {
// レスポンスからItemを取得
List<Item> items = response.body().getItems();
for(Item item : items){
Uri uri = Uri.parse(item.getSnippet().getThumbnails().getHigh().getUrl());
Uri.Builder builder = uri.buildUpon();
AsyncTaskHttpRequest task = new AsyncTaskHttpRequest(picture);
task.execute(builder);
title.setText(item.getSnippet().getTitle());
}
}
@Override
public void onFailure(Call<APIResponse> call, Throwable t) {
}
});
}
};
}
なお,URLから画像を取得し,ImageViewに表示させるのに,以下のサイトを参考にしました.上のコードをコピペしても,AsyncTaskHttpRequestクラスが未定義になるので,注意してください.
[参考]
* 【Androidプログラミング入門 #007】ネット上の画像を取得しImageViewに表示する
レイアウトファイルの実装
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="@+id/picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toTopOf="@+id/title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@mipmap/ic_launcher" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title"
app:layout_constraintVertical_bias="0.3" />
</android.support.constraint.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
tools:context=".SharedActivity">
<ImageView
android:id="@+id/thumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:padding="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.201"
app:srcCompat="@mipmap/ic_launcher" />
<TextView
android:id="@+id/movieId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="TextView"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
AndroidManifest.xml
念の為,マニフェストファイルも載せておきます.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tomiyama.noir.sharedtext">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SharedActivity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain"/>
</intent-filter>
</activity>
</application>
</manifest>
[参考]
Retrofit周りでAPIにアクセスしたりするあたりで非常に参考になりました.また,細かい点は,Githubにあげてるコードを参照してください.
* Retrofit + Gson で、 API にアクセス & JSON のパージング処理を簡潔に実装する