-
Notifications
You must be signed in to change notification settings - Fork 88
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
React Native Expo #48
Comments
Did you create a config plugin to get it to work? @csirak1528 |
no. it does not work with expo |
I created one and it works |
where is it? |
@ansh are you able to share your config plugin? |
This is @ansh plugin from another thread: |
For ios, I made the following plugin and it seems to work.
app.config.ts
|
Here is mine. You have to replace Here is my config plugin. This works and is updated. You have to compile it to JS though.
```ts
import {
AndroidConfig,
createRunOncePlugin,
ConfigPlugin,
withProjectBuildGradle,
withAndroidManifest,
XML,
withDangerousMod,
} from "@expo/config-plugins";
import {
createGeneratedHeaderComment,
MergeResults,
mergeContents,
removeGeneratedContents,
} from "@expo/config-plugins/build/utils/generateCode";
import { ExpoConfig } from "expo/config";
import * as fs from "fs-extra";
const { addMetaDataItemToMainApplication, getMainApplicationOrThrow } = AndroidConfig.Manifest;
// Fork of config-plugins mergeContents, but appends the contents to the end of the file. Taken from https://github.com/expo/expo/blob/master/packages/expo-camera/plugin/src/withCamera.ts
function appendContents({
src,
newSrc,
tag,
comment,
}: {
src: string;
newSrc: string;
tag: string;
comment: string;
}): MergeResults {
const header = createGeneratedHeaderComment(newSrc, tag, comment);
if (!src.includes(header)) {
// Ensure the old generated contents are removed.
const sanitizedTarget = removeGeneratedContents(src, tag);
const contentsToAdd = [
// @something
header,
// contents
newSrc,
// @end
`${comment} @generated end ${tag}`,
].join("\n");
return {
contents: sanitizedTarget ?? src + contentsToAdd,
didMerge: true,
didClear: !!sanitizedTarget,
};
}
return { contents: src, didClear: false, didMerge: false };
}
const PUBLIC_CLIENT_ID = "your-client-id-here";
const ANDROID_PACKAGE_NAME = "com.example.app";
const pkg = require("@snapchat/snap-kit-react-native/package.json");
const addSnapkitImport = (src: string): MergeResults => {
return appendContents({
tag: "expo-snapkit-import",
src,
newSrc: `allprojects { repositories { maven { url "https://storage.googleapis.com/snap-kit-build/maven" } } }`,
comment: "//",
});
};
const withSnapkitGradle: ConfigPlugin = (config) => {
return withProjectBuildGradle(config, (config) => {
if (config.modResults.language === "groovy") {
config.modResults.contents = addSnapkitImport(config.modResults.contents).contents;
} else {
throw new Error(
"Cannot add Snapkit maven gradle because the project build.gradle is not groovy"
);
}
return config;
});
};
async function addMetaDataToAndroidManifest(
config: Pick<ExpoConfig, "android">,
androidManifest: AndroidConfig.Manifest.AndroidManifest
): Promise<AndroidConfig.Manifest.AndroidManifest> {
const name = "com.snapchat.kit.sdk.clientId";
const value = PUBLIC_CLIENT_ID;
const mainApplication = getMainApplicationOrThrow(androidManifest); // Get the <application /> tag and assert if it doesn't exist.
addMetaDataItemToMainApplication(
mainApplication,
name, // value for `android:name`
value // value for `android:value`
);
return androidManifest;
}
const withCustomMetaData: ConfigPlugin = (config) => {
return withAndroidManifest(config, async (config) => {
// Modifiers can be async, but try to keep them fast.
config.modResults = await addMetaDataToAndroidManifest(config, config.modResults);
return config;
});
};
function addProviderToAndroidManifest(androidManifest: AndroidConfig.Manifest.AndroidManifest) {
const app = AndroidConfig.Manifest.getMainApplicationOrThrow(
androidManifest
) as AndroidConfig.Manifest.ManifestApplication & { provider?: any[] };
// Add the provider if it doesn't exist.
if (!app.provider) {
app.provider = [];
}
// if the provider doesn't have the FileProvider, add it.
if (!app.provider.some((p) => p.$["android:name"] === "androidx.core.content.FileProvider")) {
// <provider android:authorities="com.example.fileprovider" android:name="androidx.core.content.FileProvider" android:exported="false" android:grantUriPermissions="true"><meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"/></provider>
app.provider.push({
$: {
"android:name": "androidx.core.content.FileProvider",
"android:authorities": `${ANDROID_PACKAGE_NAME}.fileprovider`,
"android:exported": "false",
"android:grantUriPermissions": "true",
},
"meta-data": {
$: {
"android:name": "android.support.FILE_PROVIDER_PATHS",
"android:resource": "@xml/file_paths",
},
},
});
}
return androidManifest;
}
function withProvider(config: ExpoConfig) {
return withAndroidManifest(config, async (config) => {
config.modResults = addProviderToAndroidManifest(config.modResults);
return config;
});
}
function addPackageToQuery(androidManifest: AndroidConfig.Manifest.AndroidManifest) {
// <package android:name="com.snapchat.android" />
const PACKAGE_NAME = "com.snapchat.android";
const packageToAdd = {
package: {
$: {
"android:name": PACKAGE_NAME,
},
},
};
// @ts-ignore since queries does exist but Expo's types don't have it.
const queries = androidManifest.manifest.queries;
if (!queries) {
// @ts-ignore since queries does exist but Expo's types don't have it.
androidManifest.manifest.queries = [...packageToAdd];
} else {
// @ts-ignore
const existingQuery = androidManifest.manifest.queries[0];
const existingPackage = existingQuery.package;
if (existingPackage) {
const alreadyExists = existingPackage.some(
(pkg: any) => pkg.$["android:name"] === PACKAGE_NAME
);
if (alreadyExists) return androidManifest;
existingPackage.push(packageToAdd.package);
} else {
existingQuery.package = [
{
$: { ...packageToAdd.package.$ },
},
];
}
}
return androidManifest;
}
function withPackage(config: ExpoConfig) {
return withAndroidManifest(config, async (config) => {
config.modResults = addPackageToQuery(config.modResults);
return config;
});
}
async function writeResXml(root: string) {
const dir = "android/app/src/main/res/xml";
fs.ensureDir(dir); // ensures that the directory exists
// <?xml version="1.0" encoding="utf-8"?>
// <paths xmlns:android="http://schemas.android.com/apk/res/android">
// <files-path name="files" path="." />
// <external-files-path name="external_files" path="." />
// <external-path name="external_files" path="." />
// <cache-path name="cached_files" path="." />
// <external-cache-path name="cached_files" path="." />
// <root-path name="root" path="." />
// </paths>
const xmlObj = {
paths: {
$: {
"xmlns:android": "http://schemas.android.com/apk/res/android",
},
"files-path": {
$: {
name: "files",
path: ".",
},
},
"external-files-path": {
$: {
name: "external_files",
path: ".",
},
},
"external-path": {
$: {
name: "external_files",
path: ".",
},
},
"cache-path": {
$: {
name: "cached_files",
path: ".",
},
},
"external-cache-path": {
$: {
name: "cached_files",
path: ".",
},
},
"root-path": {
$: {
name: "root",
path: ".",
},
},
},
};
// this will rewrite the file if it exists. // TODO: fix this.
await XML.writeXMLAsync({ path: `${dir}/file_paths.xml`, xml: xmlObj });
}
function withWrittenResXml(config: ExpoConfig) {
return withDangerousMod(config, [
"android",
async (config) => {
await writeResXml(config.modRequest.projectRoot);
return config;
},
]);
}
const withSnapchatSdk: ConfigPlugin = (config) => {
return withWrittenResXml(
withPackage(withProvider(withCustomMetaData(withSnapkitGradle(config))))
);
};
export default createRunOncePlugin(withSnapchatSdk, pkg.name, pkg.version); |
Objects return as null
The text was updated successfully, but these errors were encountered: