S., Masaya
Ionic(Angular)でAdmobを導入する方法(Android編)
Ionic(Angular)でAdmobを導入する方法です。こちらはAndroidでの実装となります。iOS版はこちら。
ポイント
- capacitor-admobプラグインを使用します
- 公式の方法+依存関係の解決(この記事に方法あります)が必要です
流れ
- npmでcapacitor-admobをインストールします
- そのままだとエラーが起こるので、依存関係を解決します
- エミュレータで正しくアプリが立ち上がり依存関係が解決されていることを確認したのち、app.component.tsでアプリ情報を初期化してから読み込みたいモジュールで広告呼び出します
動作環境
Ionic4, 5, 6でAndroid SDKはAPIレベル29(Android X)で検証。28以下でもいけました。
参考文献
https://github.com/rahadur/capacitor-admob
https://developers.google.com/admob/android/test-ads?hl=ja
初期状態
IonicのTabsのデフォルトテンプレートから始めます。

appフォルダ以下の構成は下記のようになっています。
.
├── app-routing.module.ts
├── app.component.html
├── app.component.scss
├── app.component.spec.ts
├── app.component.ts
├── app.module.ts
├── explore-container
│ ├── explore-container.component.html
│ ├── explore-container.component.scss
│ ├── explore-container.component.spec.ts
│ ├── explore-container.component.ts
│ └── explore-container.module.ts
├── tab1
│ ├── tab1-routing.module.ts
│ ├── tab1.module.ts
│ ├── tab1.page.html
│ ├── tab1.page.scss
│ ├── tab1.page.spec.ts
│ └── tab1.page.ts
├── tab2
│ ├── tab2-routing.module.ts
│ ├── tab2.module.ts
│ ├── tab2.page.html
│ ├── tab2.page.scss
│ ├── tab2.page.spec.ts
│ └── tab2.page.ts
├── tab3
│ ├── tab3-routing.module.ts
│ ├── tab3.module.ts
│ ├── tab3.page.html
│ ├── tab3.page.scss
│ ├── tab3.page.spec.ts
│ └── tab3.page.ts
└── tabs
├── tabs-routing.module.ts
├── tabs.module.ts
├── tabs.page.html
├── tabs.page.scss
├── tabs.page.spec.ts
└── tabs.page.ts
実装する
1. ライブラリをインストールする
npmでcapacitor-admobをインストールします。
npm install --save capacitor-admob
2. Androidのプロジェクトを生成する
Androidのプロジェクトを生成するために下記コマンドを打ちます。capacitorを入れていない方はcapacitorを入れてください。
ionic build
npx cap add android
npx cap sync
npx cap open android
3. AndroidManifest.xmlを編集する
Androidのマニフェストファイルはアプリに機能を追加するときに編集するものです。Android Studioではデフォルトで作成されるものとなります。
ここからどのファイルを編集するか分かりにくいので詳細に記載します。非常にここは苦労しました。
デフォルトでは下記のようにAndroidが選択されていると思います。

ドリルダウンを選択してProjectを選択します

この状態にまずしてください。

マニフェストファイルはProjectのandroid/app/src/main/AndroidManifest.xmlにあります。
自分のAdmobのアプリIDに編集する必要がありますが、下記のように変更します。
<application>
<!-- this line needs to be added (replace the value!) -->
<meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="ca-app-pub-7171076285090910~XXXXXXXX" />
<activity></activity>
</application>
つまり、編集した後のファイルは下記のようになります。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.ionic.starter">
<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">
<meta-data android:name="com.google.android.gms.ads.APPLICATION_ID" android:value="ca-app-pub-7171076285090910~XXXXXXXXX" />
<activity
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"
android:name="io.ionic.starter.MainActivity"
android:label="@string/title_activity_main"
android:theme="@style/AppTheme.NoActionBarLaunch"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="@string/custom_url_scheme" />
</intent-filter>
</activity>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"></meta-data>
</provider>
</application>
<!-- Permissions -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- Camera, Photos, input file -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Geolocation API -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-feature android:name="android.hardware.location.gps" />
<!-- Network API -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Navigator.getUserMedia -->
<!-- Video -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- Audio -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
</manifest>
4. MainActivity.javaを編集する
admobをandroidに登録します。
Projectを選択した状態で、Android>app>src>main>java><your original name>>MainActivityを選択します。

そして、このように変更します。
// Other imports...
import app.xplatform.capacitor.plugins.AdMob;
public class MainActivity extends BridgeActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
add(AdMob.class); // Add AdMob as a Capacitor Plugin
}});
}
}
つまり、このようにします。
package io.ionic.starter;
import android.os.Bundle;
import com.getcapacitor.BridgeActivity;
import com.getcapacitor.Plugin;
import java.util.ArrayList;
import app.xplatform.capacitor.plugins.AdMob;
public class MainActivity extends BridgeActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Initializes the Bridge
this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
// Additional plugins you've installed go here
// Ex: add(TotallyAwesomePlugin.class);
add(AdMob.class); // Add AdMob as a Capacitor Plugin
}});
}
}
5. 公式にはないエラー処理のコードを書く
公式ではこれで完了ということですが、これだとエラーが起きます。これでエミュレータを起動すると下記のエラーが出ます。
/Users/masaya/Desktop/MyGoodness/admob-master/admob-master/node_modules/capacitor-admob/android/src/main/java/app/xplatform/capacitor/plugins/AdMob.java:4: エラー: パッケージandroid.support.design.widgetは存在しません
import android.support.design.widget.CoordinatorLayout;
そこで、焦らずに下記の対応を行います。
https://github.com/rahadur/capacitor-admob/issues/35
Admob.javaの編集
まず、エラーが出ているAdmob.javaのファイルのエラー発生している行を下記に変更します。
import androidx.coordinatorlayout.widget.CoordinatorLayout;
前のものはコメントアウトでもしておいてこのようにします。

そして、capacito-admobのbuild.gradleのdependenciesの中にimplementation ‘androidx.coordinatorlayout:coordinatorlayout:1.1.0’を追加します。
implementation 'androidx.coordinatorlayout:coordinatorlayout:1.1.0'
編集するファイルを間違えるとドツボにハマるので注意。

これでサイドエミュレータを立ち上げると下記のエラーが出ます。
2020-12-21 15:44:03.866 9236-9236/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: io.ionic.starter, PID: 9236
java.lang.RuntimeException: Unable to start activity ComponentInfo{io.ionic.starter/io.ionic.starter.MainActivity}: android.view.InflateException: Binary XML file line #2 in io.ionic.starter:layout/bridge_layout_main: Binary XML file line #2 in io.ionic.starter:layout/bridge_layout_main: Error inflating class android.support.design.widget.CoordinatorLayout
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: android.view.InflateException: Binary XML file line #2 in io.ionic.starter:layout/bridge_layout_main: Binary XML file line #2 in io.ionic.starter:layout/bridge_layout_main: Error inflating class android.support.design.widget.CoordinatorLayout
Caused by: android.view.InflateException: Binary XML file line #2 in io.ionic.starter:layout/bridge_layout_main: Error inflating class android.support.design.widget.CoordinatorLayout
Caused by: java.lang.ClassNotFoundException: android.support.design.widget.CoordinatorLayout
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:454)
at android.view.LayoutInflater.createView(LayoutInflater.java:815)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1006)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:961)
at android.view.LayoutInflater.inflate(LayoutInflater.java:659)
at android.view.LayoutInflater.inflate(LayoutInflater.java:534)
at android.view.LayoutInflater.inflate(LayoutInflater.java:481)
at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:555)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:161)
at com.getcapacitor.BridgeActivity.init(BridgeActivity.java:60)
at com.getcapacitor.BridgeActivity.init(BridgeActivity.java:48)
at io.ionic.starter.MainActivity.onCreate(MainActivity.java:17)
at android.app.Activity.performCreate(Activity.java:7802)
at android.app.Activity.performCreate(Activity.java:7791)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
2020-12-21 15:44:03.866 9236-9236/? E/AndroidRuntime: Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.design.widget.CoordinatorLayout" on path: DexPathList[[zip file "/data/app/io.ionic.starter-wIOzWpenwsyjIPlSvEtd-g==/base.apk"],nativeLibraryDirectories=[/data/app/io.ionic.starter-wIOzWpenwsyjIPlSvEtd-g==/lib/x86, /system/lib, /system/product/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:196)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
... 28 more
そこで、この辺を解決してくれるように下記のライブラリを導入します。
terminalで下記を打ちます。
npm install jetifier
npx jetify
npx cap sync android
これで再度エミュレータを起動すると、ようやく無事に立ち上がるようになります。これで依存関係が無事に解決されました。

広告を表示する
以上で広告を表示するためのプラグインの設定が終わったので、いよいよ広告をアプリで表示していきます。
まず、app.component.tsでアプリケーションを初期化します。
import { Plugins } from "@capacitor/core";
// import { initialize } from 'capacitor-admob'; No longar required
const { AdMob } = Plugins;
@Component({
selector: "app-root",
templateUrl: "app.component.html",
styleUrls: ["app.component.scss"]
})
export class AppComponent {
constructor() {
// Initialize AdMob for your Application
AdMob.initialize("YOUR APPID");
}
}
次に、読み込みたいページで任意の広告を呼び出します。ここでは、tab1でバナー広告、tab2でインタースティシャル広告を呼び出します。
テストIDを使ってください。
https://developers.google.com/admob/android/test-ads?hl=ja
tab1でバナー広告を呼び出す
import { Component } from '@angular/core';
import { Plugins } from "@capacitor/core";
import { AdOptions, AdSize, AdPosition } from "capacitor-admob";
const { AdMob } = Plugins;
@Component({
selector: 'app-tab1',
templateUrl: 'tab1.page.html',
styleUrls: ['tab1.page.scss']
})
export class Tab1Page {
options: AdOptions = {
adId: "ca-app-pub-3940256099942544/6300978111",
adSize: AdSize.BANNER,
position: AdPosition.BOTTOM_CENTER
};
constructor() {
// Show Banner Ad
AdMob.showBanner(this.options).then(
value => {
console.log(value); // true
},
error => {
console.error(error); // show error
}
);
// Subscibe Banner Event Listener
AdMob.addListener("onAdLoaded", (info: boolean) => {
console.log("Banner Ad Loaded");
});
}
}
tab2でインタースティシャルを表示する
import { Component } from '@angular/core';
import { Plugins } from "@capacitor/core";
import { AdOptions } from "capacitor-admob";
const { AdMob } = Plugins;
@Component({
selector: 'app-tab2',
templateUrl: 'tab2.page.html',
styleUrls: ['tab2.page.scss']
})
export class Tab2Page {
options: AdOptions = {
adId: "ca-app-pub-3940256099942544/1033173712",
hasTabBar: false, // make it true if you have TabBar Layout.
tabBarHeight: 56 // you can assign custom margin in pixel default is 56
};
constructor() {
// Prepare interstitial banner
AdMob.prepareInterstitial(this.options).then(
value => {
console.log(value); // true
},
error => {
console.error(error); // show error
}
);
// Subscibe Banner Event Listener
AdMob.addListener("onAdLoaded", (info: boolean) => {
// You can call showInterstitial() here or anytime you want.
console.log("Interstitial Ad Loaded");
// Show interstitial ad when it’s ready
AdMob.showInterstitial().then(
value => {
console.log(value); // true
},
error => {
console.error(error); // show error
}
);
});
}
}
時間を空ける
Admobの仕様で広告が表示されるまでに時間が必要です。
設定が正しくされていても最初は
- Ad failed to load : 2
- Ad failed to load : 0
などが表示されて広告が表示されません。これは時間をおけば解決なので少し忍耐が必要です。
その他何かうまくいかないときは下記を実行することをお勧めします。
- ionic build –prodでプロダクションモードでビルドする
- npx cap sync android
- npx cap copy
終わりに
あー記事まとめるのめっちゃ大変だった。お疲れ様でした。