가상매매 시간봉 제거
This commit is contained in:
@@ -7,8 +7,8 @@ android {
|
||||
applicationId "com.goldenchart.app"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 7
|
||||
versionName "1.6"
|
||||
versionCode 16
|
||||
versionName "2.5"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
aaptOptions {
|
||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||
@@ -40,15 +40,17 @@ dependencies {
|
||||
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
||||
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
||||
implementation project(':capacitor-cordova-android-plugins')
|
||||
implementation platform('com.google.firebase:firebase-bom:33.7.0')
|
||||
implementation 'com.google.firebase:firebase-messaging'
|
||||
implementation 'com.google.android.gms:play-services-base:18.5.0'
|
||||
}
|
||||
|
||||
apply from: 'capacitor.build.gradle'
|
||||
|
||||
try {
|
||||
def servicesJSON = file('google-services.json')
|
||||
if (servicesJSON.text) {
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
}
|
||||
} catch(Exception e) {
|
||||
logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work")
|
||||
def servicesJSON = file('google-services.json')
|
||||
if (!servicesJSON.exists()) {
|
||||
throw new GradleException(
|
||||
'google-services.json 없음. 실행: ./scripts/ensure-android-google-services.sh'
|
||||
)
|
||||
}
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
|
||||
@@ -12,7 +12,6 @@ dependencies {
|
||||
implementation project(':capacitor-app')
|
||||
implementation project(':capacitor-haptics')
|
||||
implementation project(':capacitor-preferences')
|
||||
implementation project(':capacitor-push-notifications')
|
||||
implementation project(':capacitor-splash-screen')
|
||||
implementation project(':capacitor-status-bar')
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "353782909389",
|
||||
"project_id": "goldenanalysisapp",
|
||||
"storage_bucket": "goldenanalysisapp.firebasestorage.app"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:353782909389:android:45e0218e69611efcc75c84",
|
||||
"android_client_info": {
|
||||
"package_name": "com.golden.app"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyBZWkVrPvG88_bYnIG94yiml3VXzht157Y"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:353782909389:android:62e71bbb669c64bbc75c84",
|
||||
"android_client_info": {
|
||||
"package_name": "com.goldenchart.app"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyBZWkVrPvG88_bYnIG94yiml3VXzht157Y"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": []
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
@@ -18,6 +19,16 @@
|
||||
<meta-data
|
||||
android:name="com.google.firebase.messaging.default_notification_channel_id"
|
||||
android:value="@string/default_notification_channel_id" />
|
||||
<!-- 권한 허용·앱 시작 시 FCM 자동 초기화 방지 — JS register() 시에만 활성화 -->
|
||||
<meta-data
|
||||
android:name="firebase_messaging_auto_init_enabled"
|
||||
android:value="false"
|
||||
tools:replace="android:value" />
|
||||
|
||||
<!-- Capacitor push-notifications 잔여 병합 제거 (이중 MessagingService 크래시 방지) -->
|
||||
<service
|
||||
android:name="com.capacitorjs.plugins.pushnotifications.MessagingService"
|
||||
tools:node="remove" />
|
||||
|
||||
<activity
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode|navigation"
|
||||
@@ -34,6 +45,14 @@
|
||||
|
||||
</activity>
|
||||
|
||||
<service
|
||||
android:name=".GoldenChartMessagingService"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.goldenchart.app;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.getcapacitor.JSObject;
|
||||
import com.google.firebase.messaging.FirebaseMessagingService;
|
||||
import com.google.firebase.messaging.RemoteMessage;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* FCM 수신 — JS GoldenFcm 리스너로 전달
|
||||
*/
|
||||
public class GoldenChartMessagingService extends FirebaseMessagingService {
|
||||
|
||||
@Override
|
||||
public void onNewToken(@NonNull String token) {
|
||||
super.onNewToken(token);
|
||||
GoldenFcmPlugin.emitRegistration(token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageReceived(@NonNull RemoteMessage message) {
|
||||
super.onMessageReceived(message);
|
||||
JSObject notification = new JSObject();
|
||||
RemoteMessage.Notification n = message.getNotification();
|
||||
if (n != null) {
|
||||
if (n.getTitle() != null) notification.put("title", n.getTitle());
|
||||
if (n.getBody() != null) notification.put("body", n.getBody());
|
||||
}
|
||||
JSObject data = new JSObject();
|
||||
for (Map.Entry<String, String> e : message.getData().entrySet()) {
|
||||
data.put(e.getKey(), e.getValue());
|
||||
}
|
||||
notification.put("data", data);
|
||||
GoldenFcmPlugin.emitPushReceived(notification);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
package com.goldenchart.app;
|
||||
|
||||
import android.Manifest;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
|
||||
import com.getcapacitor.JSObject;
|
||||
import com.getcapacitor.Plugin;
|
||||
import com.getcapacitor.PluginCall;
|
||||
import com.getcapacitor.PluginMethod;
|
||||
import com.getcapacitor.annotation.CapacitorPlugin;
|
||||
import com.getcapacitor.annotation.Permission;
|
||||
import com.getcapacitor.annotation.PermissionCallback;
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.GoogleApiAvailability;
|
||||
import com.google.firebase.FirebaseApp;
|
||||
import com.google.firebase.messaging.FirebaseMessaging;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* FCM — Capacitor PushNotifications 미사용 (크래시 방지)
|
||||
*/
|
||||
@CapacitorPlugin(
|
||||
name = "GoldenFcm",
|
||||
permissions = {
|
||||
@Permission(strings = { Manifest.permission.POST_NOTIFICATIONS }, alias = GoldenFcmPlugin.PERM)
|
||||
}
|
||||
)
|
||||
public class GoldenFcmPlugin extends Plugin {
|
||||
|
||||
static final String PERM = "notifications";
|
||||
private static final String TAG = "GoldenFcm";
|
||||
private static GoldenFcmPlugin instance;
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
instance = this;
|
||||
}
|
||||
|
||||
static void emitRegistration(String token) {
|
||||
if (instance == null || token == null) return;
|
||||
JSObject data = new JSObject();
|
||||
data.put("value", token);
|
||||
instance.notifyListeners("registration", data);
|
||||
}
|
||||
|
||||
static void emitRegistrationError(String message) {
|
||||
if (instance == null) return;
|
||||
JSObject data = new JSObject();
|
||||
data.put("error", message != null ? message : "unknown");
|
||||
instance.notifyListeners("registrationError", data);
|
||||
}
|
||||
|
||||
static void emitPushReceived(JSObject notification) {
|
||||
if (instance == null) return;
|
||||
instance.notifyListeners("pushNotificationReceived", notification);
|
||||
}
|
||||
|
||||
static void emitPushAction(JSObject action) {
|
||||
if (instance == null) return;
|
||||
instance.notifyListeners("pushNotificationActionPerformed", action);
|
||||
}
|
||||
|
||||
private static String permissionStateToString(com.getcapacitor.PermissionState state) {
|
||||
if (state == com.getcapacitor.PermissionState.GRANTED) return "granted";
|
||||
if (state == com.getcapacitor.PermissionState.DENIED) return "denied";
|
||||
return "prompt";
|
||||
}
|
||||
|
||||
private boolean ensurePlayServices(PluginCall call) {
|
||||
try {
|
||||
int code = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(getContext());
|
||||
if (code != ConnectionResult.SUCCESS) {
|
||||
call.reject("Google Play 서비스 필요 (코드 " + code + ")");
|
||||
return false;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
call.reject("Play 서비스 확인 실패: " + t.getMessage());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
public void checkPermissions(PluginCall call) {
|
||||
JSObject r = new JSObject();
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
||||
r.put("receive", "granted");
|
||||
call.resolve(r);
|
||||
return;
|
||||
}
|
||||
r.put("receive", permissionStateToString(getPermissionState(PERM)));
|
||||
call.resolve(r);
|
||||
}
|
||||
|
||||
/** 알림 권한만 요청 — FCM register 호출 없음 */
|
||||
@PluginMethod
|
||||
public void requestPermissions(PluginCall call) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
||||
JSObject r = new JSObject();
|
||||
r.put("receive", "granted");
|
||||
call.resolve(r);
|
||||
return;
|
||||
}
|
||||
if (getPermissionState(PERM) == com.getcapacitor.PermissionState.GRANTED) {
|
||||
JSObject r = new JSObject();
|
||||
r.put("receive", "granted");
|
||||
call.resolve(r);
|
||||
return;
|
||||
}
|
||||
call.setKeepAlive(true);
|
||||
requestPermissionForAlias(PERM, call, "onPermResult");
|
||||
}
|
||||
|
||||
@PermissionCallback
|
||||
private void onPermResult(PluginCall call) {
|
||||
new Handler(Looper.getMainLooper()).postDelayed(() -> {
|
||||
try {
|
||||
JSObject r = new JSObject();
|
||||
r.put("receive", permissionStateToString(getPermissionState(PERM)));
|
||||
call.resolve(r);
|
||||
} catch (Throwable t) {
|
||||
Log.e(TAG, "onPermResult", t);
|
||||
call.reject(t.getMessage());
|
||||
}
|
||||
}, 600);
|
||||
}
|
||||
|
||||
/** 권한 허용 후 별도 호출 — Firebase getToken */
|
||||
@PluginMethod
|
||||
public void register(PluginCall call) {
|
||||
call.setKeepAlive(true);
|
||||
|
||||
if (getActivity() == null || getActivity().isFinishing()) {
|
||||
call.reject("Activity unavailable");
|
||||
return;
|
||||
}
|
||||
if (!ensurePlayServices(call)) return;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
|
||||
&& getPermissionState(PERM) != com.getcapacitor.PermissionState.GRANTED) {
|
||||
call.reject("알림 권한이 필요합니다");
|
||||
return;
|
||||
}
|
||||
|
||||
Executors.newSingleThreadExecutor().execute(() -> {
|
||||
try {
|
||||
if (FirebaseApp.getApps(getContext()).isEmpty()) {
|
||||
FirebaseApp.initializeApp(getContext());
|
||||
}
|
||||
FirebaseMessaging.getInstance().setAutoInitEnabled(true);
|
||||
FirebaseMessaging.getInstance()
|
||||
.getToken()
|
||||
.addOnCompleteListener(task -> {
|
||||
new Handler(Looper.getMainLooper()).post(() -> {
|
||||
if (!task.isSuccessful()) {
|
||||
Exception ex = task.getException();
|
||||
String msg = ex != null ? ex.getMessage() : "getToken failed";
|
||||
Log.w(TAG, "getToken failed", ex);
|
||||
emitRegistrationError(msg);
|
||||
call.reject(msg);
|
||||
return;
|
||||
}
|
||||
String token = task.getResult();
|
||||
Log.i(TAG, "FCM token ok");
|
||||
emitRegistration(token);
|
||||
JSObject ret = new JSObject();
|
||||
ret.put("value", token);
|
||||
call.resolve(ret);
|
||||
});
|
||||
});
|
||||
} catch (Throwable t) {
|
||||
Log.e(TAG, "register", t);
|
||||
new Handler(Looper.getMainLooper()).post(() ->
|
||||
call.reject(t.getMessage() != null ? t.getMessage() : "register failed")
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
public void unregister(PluginCall call) {
|
||||
try {
|
||||
if (!FirebaseApp.getApps(getContext()).isEmpty()) {
|
||||
FirebaseMessaging.getInstance().setAutoInitEnabled(false);
|
||||
FirebaseMessaging.getInstance().deleteToken();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
Log.w(TAG, "unregister", t);
|
||||
}
|
||||
call.resolve();
|
||||
}
|
||||
}
|
||||
@@ -4,20 +4,37 @@ import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.getcapacitor.BridgeActivity;
|
||||
import com.google.firebase.FirebaseApp;
|
||||
|
||||
/**
|
||||
* Capacitor 메인 액티비티 — FCM 알림 채널 생성 (goldenApp / Android 8+)
|
||||
* Capacitor 메인 액티비티 — GoldenFcm 플러그인 + 알림 채널
|
||||
*/
|
||||
public class MainActivity extends BridgeActivity {
|
||||
|
||||
private static final String TAG = "GoldenChart";
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
registerPlugin(GoldenFcmPlugin.class);
|
||||
initFirebaseSafe();
|
||||
createNotificationChannel();
|
||||
}
|
||||
|
||||
private void initFirebaseSafe() {
|
||||
try {
|
||||
if (FirebaseApp.getApps(this).isEmpty()) {
|
||||
FirebaseApp.initializeApp(this);
|
||||
Log.i(TAG, "FirebaseApp initialized");
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
Log.w(TAG, "FirebaseApp init failed", t);
|
||||
}
|
||||
}
|
||||
|
||||
private void createNotificationChannel() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return;
|
||||
String channelId = getString(R.string.default_notification_channel_id);
|
||||
|
||||
Reference in New Issue
Block a user