creative-kit-sample
creative-kit-sample copied to clipboard
React Native Expo
Objects return as null
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: https://github.com/expo/config-plugins/issues/153
For ios, I made the following plugin and it seems to work. https://docs.snap.com/snap-kit/creative-kit/Tutorials/react-native snapchat-plugin.js
module.exports = function withSnapchat(
config,
{ snapchatClientId},
) {
if (!config.ios) {
config.ios = {};
}
if (!config.ios.infoPlist) {
config.ios.infoPlist = {};
}
config.ios.infoPlist["LSApplicationQueriesSchemes"] = [
"snapchat",
"bitmoji-sdk",
"itms-apps",
];
config.ios.infoPlist["SCSDKClientId"] = snapchatClientId;
config.ios.infoPlist["SCSDKRedirectUrl"] = "refer to creative kit react native docs for this";
config.ios.infoPlist["URL Types / Document Role"] = "Editor";
config.ios.infoPlist["URL Types / URL Identifier"] = "refer to creative kit react native docs for this";
config.ios.infoPlist["URL Types / URL Schemes "] ="refer to creative kit react native docs for this";
return config;
};
app.config.ts
...
plugins: [
["./snapchat-plugin", { snapchatClientId: "Public OAuth 2.0 Client ID" }],
...
]
Here is mine. You have to replace com.example
and PUBLIC_CLIENT_ID
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);