Gluon mobile cross-platform adsView

2019-01-28 23:36发布

问题:

Is there any way to integrate ads such as Google's Admob library into gluon mobile on either android or iOS or hopefully both?

This is the gradle file, I have downloaded the Google Play Services library and the google Repository :

buildscript {
    repositories {
        jcenter()       
    }
    dependencies {
        classpath 'org.javafxports:jfxmobile-plugin:1.2.0'
    }
}

apply plugin: 'org.javafxports.jfxmobile'

repositories {
    jcenter()
    maven {
        url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
    }
}

mainClassName = 'graphing.calculator.Calculator'

dependencies {
    compile 'com.gluonhq:charm:4.3.0'
    androidCompile 'com.google.android.gms:play-services-ads:9.4.0'
}

jfxmobile {
    downConfig {
        version = '3.2.0'
        plugins 'display', 'lifecycle', 'statusbar', 'storage'
    }
    android {
        manifest = 'src/android/AndroidManifest.xml'
        androidSdk = '/Users/aniket/Library/Android/sdk'
    }
    ios {
        arch = "arm64"
        infoPList = file('src/ios/Default-Info.plist')
        forceLinkClasses = [
                'com.gluonhq.**.*',
                'javax.annotations.**.*',
                'javax.inject.**.*',
                'javax.json.**.*',
                'org.glassfish.json.**.*'
        ]
    }
}

project.afterEvaluate {
    explodeAarDependencies(project.configurations.androidCompile)
}

回答1:

Yes, there is a way, for both Android and iOS.

This answer already contains a snippet of how it could be done on Android. But I'll update it here using and extending the Charm Down library. I won't include the iOS solution, though, as it requires modifications in the jfxmobile plugin, as I'll explain later.

Create a new project with the Gluon plugin, and modify the following. You'll have to keep the package names I mention, but you can name your project (and package) as you want.

  1. build.gradle script

You need to include the Google Play Services library:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'org.javafxports:jfxmobile-plugin:1.3.4'
    }
}

apply plugin: 'org.javafxports.jfxmobile'

repositories {
    jcenter()
    maven {
        url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
    }
}

mainClassName = 'com.gluonhq.adview.GluonAdView' // this can be changed

dependencies {
    compile 'com.gluonhq:charm:4.3.2'

    androidCompile 'com.google.android.gms:play-services-ads:9.4.0'
}

jfxmobile {
    downConfig {
        version '3.2.4'
        plugins 'display', 'lifecycle', 'statusbar', 'storage'
    }
    android {
        manifest = 'src/android/AndroidManifest.xml'
    }
    ios {
        infoPList = file('src/ios/Default-Info.plist')
        forceLinkClasses = [
                'com.gluonhq.**.*',
                'javax.annotations.**.*',
                'javax.inject.**.*',
                'javax.json.**.*',
                'org.glassfish.json.**.*'
        ]
    }
}

project.afterEvaluate {
    explodeAarDependencies(project.configurations.androidCompile)
}

Note the last task: it explodes the aar files on the android/google local repositories, to extract the jars (in this case the Google Play Services jar and all its dependencies).

Note also that after modifying the build file, you need to reload the project (to sync the project and manage the new dependencies).

  1. Source Packages/Java

Besides the project files, you need to add this package: com.gluonhq.charm.down.plugins, and these classes:

AdViewService interface

public interface AdViewService {
    void setAdUnit(String unitId, String testDeviceId, boolean test);
}

AdViewServiceFactory class

public class AdViewServiceFactory extends DefaultServiceFactory<AdViewService> {

    public AdViewServiceFactory() {
        super(AdViewService.class);
    }

}
  1. Android/Java Packages

In the Android/Java package, add this package: com.gluonhq.charm.down.plugins.android, and this class:

AndroidAdViewService class

import android.view.Gravity;
import android.widget.LinearLayout;
import com.gluonhq.charm.down.Services;
import com.gluonhq.charm.down.plugins.LifecycleEvent;
import com.gluonhq.charm.down.plugins.LifecycleService;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.AdView;
import javafxports.android.FXActivity;
import com.gluonhq.charm.down.plugins.AdViewService;

public class AndroidAdViewService implements AdViewService {

    private AdView adView;

    @Override
    public void setAdUnit(String unitId, String testDeviceId, boolean test) {
        FXActivity.getInstance().runOnUiThread(() -> {
            LinearLayout layout = new LinearLayout(FXActivity.getInstance());
            layout.setVerticalGravity(Gravity.BOTTOM);
            layout.setOrientation(LinearLayout.VERTICAL);

            adView = new AdView(FXActivity.getInstance());
            adView.setAdSize(AdSize.SMART_BANNER);
            adView.setAdUnitId(unitId);

            AdRequest adRequest;
            if (test) {
                adRequest = new AdRequest.Builder()
                    .addTestDevice(AdRequest.DEVICE_ID_EMULATOR)        // All emulators
                    .addTestDevice(testDeviceId)        // from logcat!
                    .build();
            } else {
                adRequest = new AdRequest.Builder().build();
            }

            adView.loadAd(adRequest);
            adView.setAdListener(new AdListener() {
                @Override
                public void onAdLoaded() {
                    super.onAdLoaded();
                }
            });

            layout.addView(adView);

            FXActivity.getViewGroup().addView(layout);
        });

        Services.get(LifecycleService.class).ifPresent(service -> {
            service.addListener(LifecycleEvent.RESUME, () -> FXActivity.getInstance().runOnUiThread(() -> adView.resume()));
            service.addListener(LifecycleEvent.PAUSE, () -> FXActivity.getInstance().runOnUiThread(() -> adView.pause()));
        });
    }

}

It makes use of com.google.android.gms.ads.AdView. If your Android dependencies already include Google Play Services, you won't have any problem with the imports. Otherwise, go back to step 1.

Note that I'm setting a layout where the banner will go to the bottom of the screen. Change this at your convenience.

  1. AndroidManifest.xml

You need to add this to the manifest:

<?xml version="1.0" encoding="UTF-8"?>
<manifest ...>
        <uses-permission android:name="android.permission.INTERNET"/>
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
        <application ...>
                <activity .../>
                <meta-data android:name="com.google.android.gms.version" android:value="9452000" />
                <activity android:name="com.google.android.gms.ads.AdActivity" 
                          android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
                          android:theme="@android:style/Theme.Translucent"/>
        </application>
</manifest>

Note the Google Play Services value corresponds with the 9.4.0 version.

  1. Sample

Now you can add the service to your project. For that you'll need an Ad unit Id. You can create an account on Google AdMob to add your app, and get the App ID for the banner unit.

To get the test device id, you'll have to run the app first, and find in the console the id with adb logcat.

public BasicView(String name) {
    super(name);

    Services.get(AdViewService.class).ifPresent(ads -> {
        ads.setAdUnit("ca-app-pub-17652XXXXXXXXXX/83XXXXXXXX", "0283A9A0758XXXXXXXXXXXXXXXX", true);
    });

    Label label = new Label("Hello JavaFX World!");
    ...
}
  1. Run the sample on your Android device

You should see the ads at the bottom, and some logs at the console as well.

04-02 12:42:45.352 25520 25520 I Ads     : Starting ad request.
04-02 12:42:47.844 25520 25520 I Ads     : Scheduling ad refresh 60000 milliseconds from now.
04-02 12:42:47.889 25520 25520 I Ads     : Ad finished loading.

  1. iOS

For iOS it is possible as well. The problem is that it requires downloading the Google Mobile Ads SDK, and adding the GoogleMobileAds.framework to the list of frameworks, so when compiling the native code it finds it.

This should be done in the jfxmobile-plugin, so it is out of scope in this question for now.