Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Create Expo plugin #323

Merged
merged 8 commits into from
Mar 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// @generated by expo-module-scripts
module.exports = require('expo-module-scripts/eslintrc.base.js');
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,10 @@ iOSInjectionProject/
.expo
__generated__

# expo plugin files

/plugin/src/*js

### ReactNative.Node Stack ###
# Logs

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ We on the other hand do not load ads in a WebView. We use a more complex, Native

## Can I design the ads myself?

Yes absolutely you can! There are no limiations. You can design ads that look just like your App's design and colors.
Yes absolutely you can! There are no limitations. You can design ads that look just like your App's design and colors.

## I need other ad formats too, which library do you recommend?
There are a bunch of projects trying to figure out showing ads on react-native. Most are not maintained properly. I would recommend that you use [react-native-admob/admob](https://github.com/react-native-admob/admob) by [@wjaykim](https://github.com/wjaykim). Banners, Interstitials, AdOpen and Rewarded, Rewarded Interstital ads are supported.
Expand Down
1 change: 1 addition & 0 deletions app.plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('./plugin/build/withAdmobNativeAds');
19 changes: 19 additions & 0 deletions docs/docs/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,25 @@ Install `react-native-vector-icons` to use `StarRatingView`.

Complete setup of [react-native-vector-icons ](https://github.com/oblador/react-native-vector-icons) for iOS & Android.

## Expo Setup

Add your AdMob App IDs to `app.json` or `app.config.js`.

```
{
"expo": {
"plugins": [
[
"react-native-admob-native-ads",
{
"androidAppId": "ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy",
"iosAppId": "ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"
}
]
]
}
}
```

## Android Setup

Expand Down
34,136 changes: 24,480 additions & 9,656 deletions package-lock.json

Large diffs are not rendered by default.

20 changes: 19 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,26 @@
"private": false,
"devDependencies": {
"@react-native-community/eslint-config": "^3.0.0",
"@tsconfig/node16": "^1.0.3",
"@tsconfig/react-native": "^2.0.3",
"@types/jest": "^29.2.5",
"@types/node": "^18.11.18",
"@types/react": "^18.0.26",
"@types/react-native": "^0.70.8",
"@types/react-test-renderer": "^18.0.0",
"eslint": "^7.31.0",
"eslint-config-prettier": "^8.3.0",
"prettier": "^2.3.2"
"expo": "^47.0.12",
"expo-module-scripts": "^3.0.4",
"prettier": "^2.3.2",
"typescript": "^4.9.4"
},
"scripts": {
"build": "expo-module build",
"clean": "expo-module clean",
"test": "expo-module test",
"prepare": "expo-module prepare",
"prepublishOnly": "expo-module prepublishOnly",
"expo-module": "expo-module"
}
}
1 change: 1 addition & 0 deletions plugin/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('expo-module-scripts/jest-preset-plugin');
17 changes: 17 additions & 0 deletions plugin/src/withAdmobNativeAds.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {ConfigPlugin, createRunOncePlugin} from '@expo/config-plugins';
import { withAdmobNativeAdsAndroid } from './withAdmobNativeAdsAndroid';
import { withAdmobNativeAdsGradle } from './withAdmobNativeAdsAppBuildGradle';
import { withAdmobNativeAdsPlist } from './withAdmobNativeAdsInfoPlist';
import { withAdmobNativeAdsPodNat } from './withAdmobNativeAdsPod';

const pkg = require('react-native-admob-native-ads/package.json');

const withAdmobNativeAds: ConfigPlugin = (config, props) => {
config = withAdmobNativeAdsAndroid(config, props);
config = withAdmobNativeAdsGradle(config);
config = withAdmobNativeAdsPlist(config, props);
config = withAdmobNativeAdsPodNat(config);
return config;
};

export default createRunOncePlugin(withAdmobNativeAds, pkg.name, pkg.version);
29 changes: 29 additions & 0 deletions plugin/src/withAdmobNativeAdsAndroid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {
AndroidConfig,
ConfigPlugin,
withAndroidManifest,
} from '@expo/config-plugins';

const { addMetaDataItemToMainApplication, getMainApplicationOrThrow } = AndroidConfig.Manifest;

const withAdmobNativeAdsManifest: ConfigPlugin = (config, props) => {
return withAndroidManifest(config, (config) => {
config.modResults = setAdmobNativeAdsConfig(config.modResults, props);
return config;
});
};

const setAdmobNativeAdsConfig = (androidManifest: AndroidConfig.Manifest.AndroidManifest, props: any) => {
let mainApplication = getMainApplicationOrThrow(androidManifest);
addMetaDataItemToMainApplication(
mainApplication,
'com.google.android.gms.ads.APPLICATION_ID',
props.androidAppId
);

return androidManifest;
};

export const withAdmobNativeAdsAndroid: ConfigPlugin = (config, props) => {
return withAdmobNativeAdsManifest(config, props);
};
35 changes: 35 additions & 0 deletions plugin/src/withAdmobNativeAdsAppBuildGradle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { withDangerousMod, withPlugins } from '@expo/config-plugins';
import { resolve } from 'path';
import { writeFileSync, readFileSync } from 'fs';

const withAdmobNativeAdsAppBuildGradle = (config: any) => {
return withDangerousMod(config, [
'android',
(cfg: any) => {
const { platformProjectRoot } = cfg.modRequest;
const build = resolve(platformProjectRoot, 'app/build.gradle');
const contents = readFileSync(build, 'utf-8');
const lines = contents.split('\n');
const index = lines.findIndex((line: any) =>
/dependencies\s{/.test(line)
);

writeFileSync(
build,
[
...lines.slice(0, index + 1),
` implementation "com.google.android.gms:play-services-ads:21.3.0"`,
...lines.slice(index + 1),
].join('\n')
);

return cfg;
}
]);
};

export const withAdmobNativeAdsGradle = (config: any) => {
return withPlugins(config, [
withAdmobNativeAdsAppBuildGradle,
]);
};
165 changes: 165 additions & 0 deletions plugin/src/withAdmobNativeAdsInfoPlist.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import { withInfoPlist } from '@expo/config-plugins';

const withAdmobNativeAdsInfoPlist = (config: any, props: any) => {
return withInfoPlist(config, (config) => {
config.modResults.GADApplicationIdentifier = props.iosAppId;
const identifiers = [
{
SKAdNetworkIdentifier: 'cstr6suwn9.skadnetwork',
},
{
SKAdNetworkIdentifier: '4fzdc2evr5.skadnetwork',
},
{
SKAdNetworkIdentifier: '4pfyvq9l8r.skadnetwork',
},
{
SKAdNetworkIdentifier: '2fnua5tdw4.skadnetwork',
},
{
SKAdNetworkIdentifier: 'ydx93a7ass.skadnetwork',
},
{
SKAdNetworkIdentifier: '5a6flpkh64.skadnetwork',
},
{
SKAdNetworkIdentifier: 'p78axxw29g.skadnetwork',
},
{
SKAdNetworkIdentifier: 'v72qych5uu.skadnetwork',
},
{
SKAdNetworkIdentifier: 'ludvb6z3bs.skadnetwork',
},
{
SKAdNetworkIdentifier: 'cp8zw746q7.skadnetwork',
},
{
SKAdNetworkIdentifier: 'c6k4g5qg8m.skadnetwork',
},
{
SKAdNetworkIdentifier: 's39g8k73mm.skadnetwork',
},
{
SKAdNetworkIdentifier: '3qy4746246.skadnetwork',
},
{
SKAdNetworkIdentifier: '3sh42y64q3.skadnetwork',
},
{
SKAdNetworkIdentifier: 'f38h382jlk.skadnetwork',
},
{
SKAdNetworkIdentifier: 'hs6bdukanm.skadnetwork',
},
{
SKAdNetworkIdentifier: 'prcb7njmu6.skadnetwork',
},
{
SKAdNetworkIdentifier: 'v4nxqhlyqp.skadnetwork',
},
{
SKAdNetworkIdentifier: 'wzmmz9fp6w.skadnetwork',
},
{
SKAdNetworkIdentifier: 'yclnxrl5pm.skadnetwork',
},
{
SKAdNetworkIdentifier: 't38b2kh725.skadnetwork',
},
{
SKAdNetworkIdentifier: '7ug5zh24hu.skadnetwork',
},
{
SKAdNetworkIdentifier: '9rd848q2bz.skadnetwork',
},
{
SKAdNetworkIdentifier: 'y5ghdn5j9k.skadnetwork',
},
{
SKAdNetworkIdentifier: 'n6fk4nfna4.skadnetwork',
},
{
SKAdNetworkIdentifier: 'v9wttpbfk9.skadnetwork',
},
{
SKAdNetworkIdentifier: 'n38lu8286q.skadnetwork',
},
{
SKAdNetworkIdentifier: '47vhws6wlr.skadnetwork',
},
{
SKAdNetworkIdentifier: 'kbd757ywx3.skadnetwork',
},
{
SKAdNetworkIdentifier: '9t245vhmpl.skadnetwork',
},
{
SKAdNetworkIdentifier: 'a2p9lx4jpn.skadnetwork',
},
{
SKAdNetworkIdentifier: '22mmun2rn5.skadnetwork',
},
{
SKAdNetworkIdentifier: '4468km3ulz.skadnetwork',
},
{
SKAdNetworkIdentifier: '2u9pt9hc89.skadnetwork',
},
{
SKAdNetworkIdentifier: '8s468mfl3y.skadnetwork',
},
{
SKAdNetworkIdentifier: 'av6w8kgt66.skadnetwork',
},
{
SKAdNetworkIdentifier: 'klf5c3l5u5.skadnetwork',
},
{
SKAdNetworkIdentifier: 'ppxm28t8ap.skadnetwork',
},
{
SKAdNetworkIdentifier: '424m5254lk.skadnetwork',
},
{
SKAdNetworkIdentifier: 'ecpz2srf59.skadnetwork',
},
{
SKAdNetworkIdentifier: 'uw77j35x4d.skadnetwork',
},
{
SKAdNetworkIdentifier: 'mlmmfzh3r3.skadnetwork',
},
{
SKAdNetworkIdentifier: '578prtvx9j.skadnetwork',
},
{
SKAdNetworkIdentifier: '4dzt52r2t5.skadnetwork',
},
{
SKAdNetworkIdentifier: 'gta9lk7p23.skadnetwork',
},
{
SKAdNetworkIdentifier: 'e5fvkxwrpn.skadnetwork',
},
{
SKAdNetworkIdentifier: '8c4e2ghe7u.skadnetwork',
},
{
SKAdNetworkIdentifier: 'zq492l623r.skadnetwork',
},
{
SKAdNetworkIdentifier: '3rd42ekr43.skadnetwork',
},
{
SKAdNetworkIdentifier: '3qcr597p9d.skadnetwork',
}
];
config.modResults.SKAdNetworkItems = identifiers;
return config;
});
};

export const withAdmobNativeAdsPlist = (config: any, props: any) => {
return withAdmobNativeAdsInfoPlist(config, props);
};
36 changes: 36 additions & 0 deletions plugin/src/withAdmobNativeAdsPod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { withDangerousMod, withPlugins } from '@expo/config-plugins';
import { resolve } from 'path';
import { writeFileSync, readFileSync } from 'fs';

const withAdmobNativeAdsPod = (config: any) => {
return withDangerousMod(config, [
'ios',
(cfg) => {
const { platformProjectRoot } = cfg.modRequest;
const podfile = resolve(platformProjectRoot, 'Podfile');
const contents = readFileSync(podfile, 'utf-8');
const lines = contents.split('\n');
const index = lines.findIndex((line: string) =>
/\s+use_expo_modules!/.test(line)
);

writeFileSync(
podfile,
[
...lines.slice(0, index),
` pod 'Google-Mobile-Ads-SDK'`,
` pod 'GoogleMobileAdsMediationFacebook', '6.11.0.0'`,
...lines.slice(index),
].join('\n')
);

return cfg;
}
]);
};

export const withAdmobNativeAdsPodNat = (config: any) => {
return withPlugins(config, [
withAdmobNativeAdsPod,
]);
};
9 changes: 9 additions & 0 deletions plugin/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "expo-module-scripts/tsconfig.plugin",
"compilerOptions": {
"outDir": "build",
"rootDir": "src"
},
"include": ["./src"],
"exclude": ["**/__mocks__/*", "**/__tests__/*"]
}
11 changes: 11 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"target": "ESNext",
"jsx": "react-native",
"module": "commonjs",
"forceConsistentCasingInFileNames": true,
"strict": true,
"alwaysStrict": true,
"skipLibCheck": true
}
}