Skip to content

Commit c792260

Browse files
authored
Merge pull request #2566 from StoDevX/push-notifications
Add Push Notifications Capability
2 parents d6c7002 + 82de4ed commit c792260

File tree

20 files changed

+643
-5
lines changed

20 files changed

+643
-5
lines changed

android/app/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ android {
114114
manifestApplicationId: applicationId,
115115
BUGSNAG_KEY: System.getenv("BUGSNAG_KEY") ?: "",
116116
GMAPS_KEY: System.getenv("GMAPS_KEY") ?: "",
117+
onesignal_app_id: "a46c6f2f-a240-4908-a359-801911e9b9ea",
118+
onesignal_google_project_number: "REMOTE",
117119
]
118120

119121
ndk {
@@ -229,6 +231,7 @@ dependencies {
229231
implementation project(':react-native-keychain')
230232
implementation project(':react-native-linear-gradient')
231233
implementation project(':react-native-network-info')
234+
implementation project(':react-native-onesignal')
232235
implementation project(':react-native-restart')
233236
implementation project(':react-native-vector-icons')
234237
// this is for react-native itself

android/app/src/main/java/com/allaboutolaf/MainApplication.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import com.facebook.react.ReactPackage;
1717
import com.facebook.react.shell.MainReactPackage;
1818
import com.facebook.soloader.SoLoader;
19+
import com.geektime.rnonesignalandroid.ReactNativeOneSignalPackage;
1920
import com.github.droibit.android.reactnative.customtabs.CustomTabsPackage;
2021
import com.idehub.GoogleAnalyticsBridge.GoogleAnalyticsBridgePackage;
2122
import com.learnium.RNDeviceInfo.RNDeviceInfo;
@@ -49,6 +50,7 @@ protected List<ReactPackage> getPackages() {
4950
new KeychainPackage(),
5051
new LinearGradientPackage(),
5152
new RCTMGLPackage(),
53+
new ReactNativeOneSignalPackage(),
5254
new ReactNativeRestartPackage(),
5355
new RNDeviceInfo(),
5456
new RNNetworkInfoPackage(),

android/settings.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ project(':react-native-linear-gradient').projectDir = new File(rootProject.proje
2929
include ':react-native-network-info'
3030
project(':react-native-network-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-network-info/android')
3131

32+
include ':react-native-onesignal'
33+
project(':react-native-onesignal').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-onesignal/android')
34+
3235
include ':react-native-restart'
3336
project(':react-native-restart').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-restart/android')
3437

fastlane/Appfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ app_identifier 'NFMTHAZVS9.com.drewvolz.stolaf'
33

44
# Your Apple email address
55
6+
apple_dev_portal_id '[email protected]'
67

78
# Your Apple Developer Team ID, if you are in multiple teams
89
team_id 'TMK6S7TPX2'

fastlane/Fastfile

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@ before_all do
2828

2929
# set up other global shared values
3030
lane_context[:PRETTY_APP_NAME] = 'All About Olaf'
31-
31+
lane_context[:ONESIGNAL_APP_NAME] = 'All About Olaf'
32+
lane_context[:ONESIGNAL_APP_ID] = 'a46c6f2f-a240-4908-a359-801911e9b9ea'
3233
lane_context[:GRADLE_FILE] = "#{ENV['FL_GRADLE_PROJECT_DIR']}/app/build.gradle"
34+
lane_context[:APPLE_APP_ID] = CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier)
35+
lane_context[:APPLE_APP_NAME] = 'All About Olaf'
36+
lane_context[:APPLE_PUSH_EXTENSION_ID] = 'NFMTHAZVS9.com.drewvolz.stolaf.onesignal-notification-service-extension'
37+
lane_context[:APPLE_PUSH_EXTENSION_NAME] = 'All About Olaf OneSignal Notification Service Extension'
3338

3439
UI.message "GYM_PROJECT is #{ENV['GYM_PROJECT']}"
3540
UI.message "GYM_SCHEME is #{ENV['GYM_SCHEME']}"
@@ -39,6 +44,8 @@ before_all do
3944
UI.message "PRETTY_APP_NAME is #{lane_context[:PRETTY_APP_NAME]}"
4045
UI.message "GRADLE_FILE is #{lane_context[:GRADLE_FILE]}"
4146
UI.message "PLATFORM_NAME is #{lane_context[:PLATFORM_NAME]}"
47+
UI.message "ONESIGNAL_APP_NAME is #{lane_context[:ONESIGNAL_APP_NAME]}"
48+
UI.message "ONESIGNAL_APP_ID is #{lane_context[:ONESIGNAL_APP_ID]}"
4249
end
4350

4451
import 'lib/commands.rb'

fastlane/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,26 @@ Upload dYSM symbols to Bugsnag from Apple
100100
fastlane ios ci-run
101101
```
102102
Run iOS builds or tests, as appropriate
103+
### ios certificates
104+
```
105+
fastlane ios certificates
106+
```
107+
Fetch certs for both the app and any extensions
108+
### ios bootstrap
109+
```
110+
fastlane ios bootstrap
111+
```
112+
Ensure that everything is set up (must be run manually, as it needs a 2FA code)
113+
### ios generate_certificates
114+
```
115+
fastlane ios generate_certificates
116+
```
117+
Generate certs for the app and for any extensions
118+
### ios generate_pem
119+
```
120+
fastlane ios generate_pem
121+
```
122+
Generate the push notification cert and upload it to OneSignal
103123

104124
----
105125

fastlane/actions/onesignal.rb

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
module Fastlane
2+
module Actions
3+
module SharedValues
4+
ONE_SIGNAL_APP_ID = :ONE_SIGNAL_APP_ID
5+
ONE_SIGNAL_APP_AUTH_KEY = :ONE_SIGNAL_APP_AUTH_KEY
6+
end
7+
8+
class OnesignalAction < Action
9+
def self.run(params)
10+
require 'net/http'
11+
require 'uri'
12+
require 'base64'
13+
14+
UI.message("OneSignal App Name: #{params[:app_name]}")
15+
UI.message("OneSignal App ID: #{params[:app_id]}")
16+
auth_token = params[:auth_token]
17+
app_name = params[:app_name]
18+
app_id = params[:app_id]
19+
apns_p12_password = params[:apns_p12_password]
20+
android_token = params[:android_token]
21+
android_gcm_sender_id = params[:android_gcm_sender_id]
22+
23+
payload = {}
24+
payload['name'] = app_name
25+
26+
unless params[:apns_p12].nil?
27+
data = File.read(params[:apns_p12])
28+
apns_p12 = Base64.encode64(data)
29+
payload["apns_env"] = params[:apns_env]
30+
payload["apns_p12"] = apns_p12
31+
# we need to have something for the p12 password, even if it's an empty string
32+
payload["apns_p12_password"] = apns_p12_password || ""
33+
end
34+
35+
payload["gcm_key"] = android_token unless android_token.nil?
36+
payload["android_gcm_sender_id"] = android_gcm_sender_id unless android_gcm_sender_id.nil?
37+
38+
# here's the actual lifting - POST/PUT to OneSignal
39+
40+
headers = {
41+
'Content-Type' => 'application/json',
42+
'Authorization' => "Basic #{auth_token}",
43+
}
44+
45+
if app_id
46+
uri = URI.parse("https://onesignal.com/api/v1/apps/#{app_id}")
47+
http = Net::HTTP.new(uri.host, uri.port)
48+
http.use_ssl = true
49+
response = http.put(uri.path, payload.to_json, headers)
50+
else
51+
uri = URI.parse("https://onesignal.com/api/v1/apps")
52+
http = Net::HTTP.new(uri.host, uri.port)
53+
http.use_ssl = true
54+
response = http.post(uri.path, payload.to_json, headers)
55+
end
56+
57+
case response.code.to_i
58+
when 200, 204
59+
response_body = JSON.parse(response.body)
60+
61+
Actions.lane_context[SharedValues::ONE_SIGNAL_APP_ID] = response_body["id"]
62+
Actions.lane_context[SharedValues::ONE_SIGNAL_APP_AUTH_KEY] = response_body["basic_auth_key"]
63+
64+
if app_id
65+
puts("Successfully updated OneSignal app".green)
66+
else
67+
puts("Successfully created new OneSignal app".green)
68+
end
69+
else
70+
UI.user_error!("Unexpected #{response.code} with response: #{response.body}")
71+
end
72+
end
73+
74+
def self.description
75+
"Create a new OneSignal application"
76+
end
77+
78+
def self.details
79+
"You can use this action to automatically create a OneSignal application. You can also upload a `.p12` with password, a GCM key, or both."
80+
end
81+
82+
def self.available_options
83+
[
84+
FastlaneCore::ConfigItem.new(key: :auth_token,
85+
env_name: "ONE_SIGNAL_AUTH_KEY",
86+
sensitive: true,
87+
description: "OneSignal Authorization Key",
88+
verify_block: proc do |value|
89+
unless value.to_s.length > 0
90+
UI.error("Please add 'ENV[\"ONE_SIGNAL_AUTH_KEY\"] = \"your token\"' to your Fastfile's `before_all` section.")
91+
UI.user_error!("No ONE_SIGNAL_AUTH_KEY given.")
92+
end
93+
end),
94+
95+
FastlaneCore::ConfigItem.new(key: :app_name,
96+
env_name: "ONE_SIGNAL_APP_NAME",
97+
description: "OneSignal App Name",
98+
verify_block: proc do |value|
99+
unless value.to_s.length > 0
100+
UI.error("Please add 'ENV[\"ONE_SIGNAL_APP_NAME\"] = \"Your app name\"' to your Fastfile's `before_all` section.")
101+
UI.user_error!("No ONE_SIGNAL_APP_NAME given.")
102+
end
103+
end),
104+
105+
FastlaneCore::ConfigItem.new(key: :app_id,
106+
env_name: "ONE_SIGNAL_APP_ID",
107+
description: "Existing OneSignal App ID",
108+
optional: true,
109+
verify_block: proc do |value|
110+
unless value.to_s.length > 0
111+
UI.error("Please add 'ENV[\"ONE_SIGNAL_APP_ID\"] = \"Your existing OneSignal ID\"' to your Fastfile's `before_all` section.")
112+
UI.user_error!("No ONE_SIGNAL_APP_ID given.")
113+
end
114+
end),
115+
116+
FastlaneCore::ConfigItem.new(key: :android_token,
117+
env_name: "ANDROID_TOKEN",
118+
description: "ANDROID GCM KEY",
119+
sensitive: true,
120+
optional: true),
121+
122+
FastlaneCore::ConfigItem.new(key: :android_gcm_sender_id,
123+
env_name: "ANDROID_GCM_SENDER_ID",
124+
description: "GCM SENDER ID",
125+
sensitive: true,
126+
optional: true),
127+
128+
FastlaneCore::ConfigItem.new(key: :apns_p12,
129+
env_name: "APNS_P12",
130+
description: "APNS P12 File (in .p12 format)",
131+
optional: true),
132+
133+
FastlaneCore::ConfigItem.new(key: :apns_p12_password,
134+
env_name: "APNS_P12_PASSWORD",
135+
sensitive: true,
136+
description: "APNS P12 password",
137+
optional: true),
138+
139+
FastlaneCore::ConfigItem.new(key: :apns_env,
140+
env_name: "APNS_ENV",
141+
description: "APNS environment",
142+
optional: true,
143+
default_value: 'production')
144+
]
145+
end
146+
147+
def self.output
148+
[
149+
['ONE_SIGNAL_APP_ID', 'The OneSignal app ID of the newly created app'],
150+
['ONE_SIGNAL_APP_AUTH_KEY', 'The auth token for the newly created OneSignal app']
151+
]
152+
end
153+
154+
def self.authors
155+
["timothybarraclough", "smartshowltd", "hawkrives"]
156+
end
157+
158+
def self.is_supported?(platform)
159+
[:ios, :android].include?(platform)
160+
end
161+
162+
def self.example_code
163+
[
164+
'onesignal(
165+
auth_token: "Your OneSignal Auth Token",
166+
app_name: "Name for new OneSignal App",
167+
app_id: "ID of an existing OneSignal App",
168+
android_token: "Your Android GCM key (optional)",
169+
android_gcm_sender_id: "Your Android GCM Sender ID (optional)",
170+
apns_p12: "Path to Apple .p12 file (optional)",
171+
apns_p12_password: "Password for .p12 file (optional)",
172+
apns_env: "production/sandbox (defaults to production)"
173+
)'
174+
]
175+
end
176+
177+
def self.category
178+
:push
179+
end
180+
end
181+
end
182+
end

fastlane/platforms/ios.rb

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858

5959
desc 'Builds and exports the app'
6060
lane :build do
61-
match(type: 'appstore', readonly: true)
61+
certificates(type: 'appstore')
6262
propagate_version
6363

6464
# save it to a log file for later use
@@ -120,4 +120,81 @@
120120
# go ahead and download dSYMs for bugsnag too
121121
# refresh_dsyms if circle?
122122
end
123+
124+
desc 'Fetch certs for both the app and any extensions'
125+
lane :certificates do |options|
126+
app = lane_context[:APPLE_APP_ID]
127+
push_extension = lane_context[:APPLE_PUSH_EXTENSION_ID]
128+
129+
match(app_identifier: [app, push_extension],
130+
type: options[:type],
131+
readonly: true)
132+
end
133+
134+
desc 'Ensure that everything is set up (must be run manually, as it needs a 2FA code)'
135+
lane :bootstrap do
136+
generate_apps
137+
generate_certificates
138+
generate_pem
139+
end
140+
141+
desc 'Generate the app and any extensions on the Apple Developer Portal / App Store Connect'
142+
private_lane :generate_apps do
143+
produce(
144+
app_identifier: lane_context[:APPLE_APP_ID],
145+
app_name: lane_context[:APPLE_APP_NAME],
146+
language: 'English',
147+
enable_services: {
148+
push_notification: 'on',
149+
},
150+
)
151+
152+
produce(
153+
app_identifier: lane_context[:APPLE_PUSH_EXTENSION_ID],
154+
app_name: lane_context[:APPLE_PUSH_EXTENSION_NAME],
155+
language: 'English',
156+
skip_itc: 'on',
157+
enable_services: {
158+
push_notification: 'off',
159+
},
160+
)
161+
end
162+
163+
desc 'Generate certs for the app and for any extensions'
164+
lane :generate_certificates do
165+
app = lane_context[:APPLE_APP_ID]
166+
push_extension = lane_context[:APPLE_PUSH_EXTENSION_ID]
167+
168+
match(app_identifier: [app, push_extension], type: 'adhoc', readonly: false, force: true)
169+
match(app_identifier: [app, push_extension], type: 'appstore', readonly: false, force: true)
170+
end
171+
172+
desc 'Generate the push notification cert and upload it to OneSignal'
173+
lane :generate_pem do
174+
password = 'password'
175+
env_key = 'ONESIGNAL_KEY'
176+
177+
unless ENV.has_key?(env_key)
178+
raise "You do not have the #{env_key} environment variable configured. Not generating push certificate nor uploading to OneSignal."
179+
end
180+
181+
get_push_certificate(
182+
app_identifier: lane_context[:APPLE_APP_ID],
183+
pem_name: 'push_cert',
184+
generate_p12: true,
185+
p12_password: password,
186+
new_profile: proc do |profile_path|
187+
p12 = profile_path.sub('.pem', '.p12')
188+
189+
onesignal(
190+
auth_token: ENV[env_key],
191+
app_name: lane_context[:ONESIGNAL_APP_NAME],
192+
app_id: lane_context[:ONESIGNAL_APP_ID],
193+
apns_p12: p12,
194+
apns_p12_password: password,
195+
apns_env: 'production',
196+
)
197+
end
198+
)
199+
end
123200
end

0 commit comments

Comments
 (0)