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: Add Wake Lock Permission with replace configuration in AndroidManifest.xml #6

Merged
merged 5 commits into from
May 22, 2024
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
25 changes: 18 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,27 @@ If you want to enable it only for staging, not the production build (obviously),
```js
plugins: [
[
'expo-chucker',
"expo-chucker",
{
enabled: process.env.APP_ENV === 'staging' // Only enable Chucker on staging environment
}
]
]
enabled: process.env.APP_ENV === "staging", // Only enable Chucker on staging environment
},
],
];
```

Don't forget to prebuild your app each time you made changes to the config.

# Contributing
### Example App

1. Clone this repo
2. Run `yarn install` to install the dependencies
3. Run `yarn build` to build the expo plugin
4. Goto `example` directory
5. Run `yarn install` to install the dependencies for the example app
6. You need to have firebase project and get the `google-services.json` and `GoogleService-Info.plist` and put it in the `example/` directory. This is required for testing the push notification feature crashed by chucker library (see [here](https://github.com/ChuckerTeam/chucker/issues/1077))
7. Run `yarn prebuild` to prebuild the app
8. Run `yarn android` to run the app on android device or emulator

### Contributing

Contributions are very welcome! Please refer to guidelines described in the [contributing guide](https://github.com/expo/expo#contributing).
Contributions are very welcome!.
2 changes: 2 additions & 0 deletions example/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,5 @@ yarn-error.*

ios/
android/
google-services.json
GoogleService-Info.plist
46 changes: 0 additions & 46 deletions example/App.tsx

This file was deleted.

34 changes: 33 additions & 1 deletion example/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,49 @@ export default (): ExpoConfig => {
ios: {
supportsTablet: true,
bundleIdentifier: "com.chucker.example",
googleServicesFile: "./GoogleService-Info.plist",
privacyManifests: {
NSPrivacyAccessedAPITypes: [
{
NSPrivacyAccessedAPIType:
"NSPrivacyAccessedAPICategoryUserDefaults",
NSPrivacyAccessedAPITypeReasons: ["CA92.1"],
},
],
},
},
android: {
adaptiveIcon: {
foregroundImage: "./assets/adaptive-icon.png",
backgroundColor: "#ffffff",
},
package: "com.chucker.example",
googleServicesFile: "./google-services.json",
},
web: {
favicon: "./assets/favicon.png",
},
plugins: [["../app.plugin.js", { enabled: true }]],
plugins: [
"@react-native-firebase/app",
[
"expo-build-properties",
{
android: {
extraMavenRepos: [
"../../node_modules/@notifee/react-native/android/libs",
],
},
ios: {
useFrameworks: "static",
},
},
],
[
"../app.plugin.js",
{
enabled: true,
},
],
],
};
};
5 changes: 5 additions & 0 deletions example/firebase.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"react-native": {
"messaging_android_notification_channel_id": "high-priority"
}
}
4 changes: 4 additions & 0 deletions example/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { registerRootComponent } from "expo";
import App from "./src";

registerRootComponent(App);
19 changes: 12 additions & 7 deletions example/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "expo-chucker-example",
"version": "1.0.0",
"main": "node_modules/expo/AppEntry.js",
"main": "./index.js",
"scripts": {
"prebuild": "expo prebuild",
"start": "expo start",
Expand All @@ -10,15 +10,20 @@
"web": "expo start --web"
},
"dependencies": {
"expo": "^50.0.7",
"expo-splash-screen": "~0.26.4",
"expo-status-bar": "~1.11.1",
"@notifee/react-native": "^7.8.2",
"@react-native-firebase/app": "^20.0.0",
"@react-native-firebase/messaging": "^20.0.0",
"expo": "^51.0.0",
"expo-build-properties": "~0.12.1",
"expo-splash-screen": "~0.27.4",
"expo-status-bar": "~1.12.1",
"expo-system-ui": "~3.0.4",
"react": "18.2.0",
"react-native": "0.73.4"
"react-native": "0.74.1"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@types/react": "~18.2.45",
"@babel/core": "^7.24.0",
"@types/react": "~18.2.79",
"babel-plugin-module-resolver": "^5.0.0",
"typescript": "^5.1.3"
},
Expand Down
21 changes: 21 additions & 0 deletions example/src/hooks/use-device-token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import messaging from "@react-native-firebase/messaging";
import { useEffect, useState } from "react";

export const useDeviceToken = (enabled: boolean = true) => {
const [deviceToken, setDeviceToken] = useState<string>();

useEffect(() => {
messaging()
.registerDeviceForRemoteMessages()
.then(async () => {
const token = await messaging().getToken();

if (token) {
console.log("Device token:", token);
setDeviceToken(token);
}
});
}, [enabled]);

return deviceToken;
};
33 changes: 33 additions & 0 deletions example/src/hooks/use-github-user.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useEffect, useState } from "react";

export interface User {
id: number;
login: string;
avatar_url: string;
url: string;
}

export const getGithubUsers = async (): Promise<User[]> => {
try {
const response = await fetch("https://api.github.com/users");
const users = await response.json();
return users as User[];
} catch (e) {
console.error(e);
return [];
}
};

export const useGithubUsers = (enabled: boolean = true) => {
const [users, setUsers] = useState<User[]>([]);

useEffect(() => {
if (!enabled) {
return;
}

getGithubUsers().then((users) => setUsers(users));
}, [enabled]);

return users;
};
28 changes: 28 additions & 0 deletions example/src/hooks/use-notification-permission.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import notifee, { AuthorizationStatus } from "@notifee/react-native";
import messaging from "@react-native-firebase/messaging";
import { useEffect, useState } from "react";

export function useNotificationPermission() {
const [enabled, setEnabled] = useState(false);

useEffect(() => {
Promise.all([
messaging().requestPermission(),
notifee.requestPermission(),
]).then(([authStatus, notifStatus]) => {
const enabled =
authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authStatus === messaging.AuthorizationStatus.PROVISIONAL;

const localNotificationGranted =
notifStatus.authorizationStatus === AuthorizationStatus.AUTHORIZED;

console.log("Authorization status:", authStatus);
console.log("Local notification status:", notifStatus);

setEnabled(enabled && localNotificationGranted);
});
}, []);

return enabled;
}
47 changes: 47 additions & 0 deletions example/src/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { FlatList, SafeAreaView, StyleSheet, Text } from "react-native";
import { useDeviceToken } from "./hooks/use-device-token";
import { useGithubUsers } from "./hooks/use-github-user";
import { useNotificationPermission } from "./hooks/use-notification-permission";
import "./utils/set-background-notification-handler";

export default function App() {
const isPermissionGranted = useNotificationPermission();
const deviceToken = useDeviceToken(isPermissionGranted);
const users = useGithubUsers(isPermissionGranted);

return (
<SafeAreaView style={styles.container}>
<Text style={styles.text} selectable>
{isPermissionGranted
? "Notification permission granted"
: "No notification permission"}
</Text>

<Text style={styles.text} selectable>
{deviceToken ? `Device token: ${deviceToken}` : "No device token"}
</Text>

<FlatList
data={users}
renderItem={({ item }) => (
<Text selectable style={[styles.text, { marginBottom: 8 }]}>
{item.login}
</Text>
)}
/>
</SafeAreaView>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
},
text: {
marginBottom: 16,
marginHorizontal: 16,
fontSize: 14,
textAlign: "left",
},
});
21 changes: 21 additions & 0 deletions example/src/utils/create-local-notification.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import notifee from "@notifee/react-native";

export async function createLocalNotification(title: string, body: string) {
// Request permissions (required for iOS)
await notifee.requestPermission();

// Create a channel (required for Android)
const channelId = await notifee.createChannel({
id: "high-priority",
name: "High Priority Notifications",
});

// Display a notification
await notifee.displayNotification({
title,
body,
android: {
channelId,
},
});
}
11 changes: 11 additions & 0 deletions example/src/utils/set-background-notification-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import messaging from "@react-native-firebase/messaging";
import { createLocalNotification } from "./create-local-notification";

messaging().setBackgroundMessageHandler(async (remoteMessage) => {
console.log("Message handled in the background!", remoteMessage);

await createLocalNotification(
remoteMessage.notification?.title ?? "No title",
remoteMessage.notification?.body ?? "No body"
);
});
Loading