fix bugs
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
|
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
|
||||||
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
|
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
@@ -50,6 +51,24 @@
|
|||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:foregroundServiceType="dataSync"
|
android:foregroundServiceType="dataSync"
|
||||||
android:stopWithTask="false" />
|
android:stopWithTask="false" />
|
||||||
|
<activity
|
||||||
|
android:name=".IncomingCallActivity"
|
||||||
|
android:exported="false"
|
||||||
|
android:theme="@style/AppCallTheme"
|
||||||
|
android:showOnLockScreen="true"
|
||||||
|
android:showWhenLocked="true"
|
||||||
|
android:turnScreenOn="true"
|
||||||
|
android:launchMode="singleInstance"
|
||||||
|
android:excludeFromRecents="true"
|
||||||
|
android:screenOrientation="portrait" />
|
||||||
|
<receiver
|
||||||
|
android:name=".CallActionReceiver"
|
||||||
|
android:exported="false">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.rnpay.CALL_ACCEPT" />
|
||||||
|
<action android:name="com.rnpay.CALL_DECLINE" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
<!-- 避免 Firebase SDK 默认 Service 抢收 data-only FCM -->
|
<!-- 避免 Firebase SDK 默认 Service 抢收 data-only FCM -->
|
||||||
<service
|
<service
|
||||||
android:name="com.google.firebase.messaging.FirebaseMessagingService"
|
android:name="com.google.firebase.messaging.FirebaseMessagingService"
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.rnpay;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import com.rnwalletman.IncomingCallNotificationHelper;
|
||||||
|
|
||||||
|
/** 处理来电通知里的接听 / 挂断动作 */
|
||||||
|
public class CallActionReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
|
public static final String ACTION_ACCEPT = "com.rnpay.CALL_ACCEPT";
|
||||||
|
public static final String ACTION_DECLINE = "com.rnpay.CALL_DECLINE";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context ctx, Intent intent) {
|
||||||
|
String action = intent.getAction();
|
||||||
|
IncomingCallNotificationHelper.cancel(ctx);
|
||||||
|
|
||||||
|
if (ACTION_ACCEPT.equals(action)) {
|
||||||
|
String caller = intent.getStringExtra("caller");
|
||||||
|
Intent launch = ctx.getPackageManager().getLaunchIntentForPackage(ctx.getPackageName());
|
||||||
|
if (launch != null) {
|
||||||
|
launch.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
|
launch.putExtra("from_call", true);
|
||||||
|
launch.putExtra("caller", caller);
|
||||||
|
ctx.startActivity(launch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ACTION_DECLINE: 只取消通知即可
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,221 @@
|
|||||||
|
package com.rnpay;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.drawable.GradientDrawable;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.CountDownTimer;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.rnwalletman.IncomingCallNotificationHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全屏来电界面,1:1 还原 gbpay StrongCallActivity / activity_strong_call.xml 布局结构与数值。
|
||||||
|
*
|
||||||
|
* 布局层次:
|
||||||
|
* FrameLayout root (bg: #6a6b6f → #393d43 gradient)
|
||||||
|
* └─ LinearLayout top (gravity=top|center_horizontal, marginTop=120dp)
|
||||||
|
* ├─ TextView callerName (24sp bold white, marginBottom=8dp)
|
||||||
|
* └─ TextView subtitle (12sp #d9d9d9)
|
||||||
|
* └─ ImageView avatar (center, 100dp oval #a4a4a4, padding=10dp)
|
||||||
|
* └─ LinearLayout btnRow (bottom, marginBottom=78dp, marginH=13dp,
|
||||||
|
* bg rect corner=35dp #4d828282, paddingV=5dp)
|
||||||
|
* ├─ ImageView decline (oval #e53935, 56dp, margin=12dp) ← hangup
|
||||||
|
* ├─ ImageView btnMic (oval #a4a4a4, 56dp, margin=12dp) ← decorative
|
||||||
|
* ├─ ImageView btnVol (oval #a4a4a4, 56dp, margin=12dp) ← decorative
|
||||||
|
* └─ ImageView accept (oval #17b834, 56dp, margin=12dp) ← accept call
|
||||||
|
*/
|
||||||
|
public class IncomingCallActivity extends Activity {
|
||||||
|
|
||||||
|
private CountDownTimer countDown;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
// 锁屏 & 亮屏标志
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
||||||
|
setShowWhenLocked(true);
|
||||||
|
setTurnScreenOn(true);
|
||||||
|
} else {
|
||||||
|
//noinspection deprecation
|
||||||
|
getWindow().addFlags(
|
||||||
|
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
|
||||||
|
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
|
||||||
|
}
|
||||||
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||||
|
|
||||||
|
String caller = getIntent().getStringExtra("caller");
|
||||||
|
int ringDuration = getIntent().getIntExtra("ringDuration", 30);
|
||||||
|
boolean autoAccept = getIntent().getBooleanExtra("auto_accept", false);
|
||||||
|
if (caller == null || caller.isEmpty()) caller = "Unknown";
|
||||||
|
|
||||||
|
// 通知栏接听按钮直接触发:跳过 UI,直接进 app
|
||||||
|
if (autoAccept) {
|
||||||
|
IncomingCallNotificationHelper.cancel(this);
|
||||||
|
Intent launch = getPackageManager().getLaunchIntentForPackage(getPackageName());
|
||||||
|
if (launch != null) {
|
||||||
|
launch.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
|
launch.putExtra("from_call", true);
|
||||||
|
launch.putExtra("caller", caller);
|
||||||
|
startActivity(launch);
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── root: 渐变背景 #6a6b6f → #393d43 ─────────────────────────────────
|
||||||
|
FrameLayout root = new FrameLayout(this);
|
||||||
|
GradientDrawable bg = new GradientDrawable(
|
||||||
|
GradientDrawable.Orientation.TOP_BOTTOM,
|
||||||
|
new int[]{0xFF6a6b6f, 0xFF393d43});
|
||||||
|
root.setBackground(bg);
|
||||||
|
setContentView(root);
|
||||||
|
|
||||||
|
// ── 顶部文字区域(marginTop=120dp)────────────────────────────────────
|
||||||
|
LinearLayout top = new LinearLayout(this);
|
||||||
|
top.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
top.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||||
|
FrameLayout.LayoutParams topLp = new FrameLayout.LayoutParams(
|
||||||
|
FrameLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
FrameLayout.LayoutParams.WRAP_CONTENT);
|
||||||
|
topLp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
|
||||||
|
topLp.topMargin = dp(120);
|
||||||
|
top.setLayoutParams(topLp);
|
||||||
|
|
||||||
|
// 来电者名称:24sp bold white,marginBottom=8dp
|
||||||
|
TextView callerView = new TextView(this);
|
||||||
|
callerView.setText(caller);
|
||||||
|
callerView.setTextSize(24);
|
||||||
|
callerView.setTextColor(Color.WHITE);
|
||||||
|
callerView.setTypeface(android.graphics.Typeface.DEFAULT_BOLD);
|
||||||
|
callerView.setGravity(Gravity.CENTER);
|
||||||
|
LinearLayout.LayoutParams callerLp = new LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||||
|
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||||
|
callerLp.bottomMargin = dp(8);
|
||||||
|
callerView.setLayoutParams(callerLp);
|
||||||
|
top.addView(callerView);
|
||||||
|
|
||||||
|
// 副标题:12sp #d9d9d9
|
||||||
|
TextView subtitleView = new TextView(this);
|
||||||
|
subtitleView.setText("Incoming call...");
|
||||||
|
subtitleView.setTextSize(12);
|
||||||
|
subtitleView.setTextColor(0xFFd9d9d9);
|
||||||
|
subtitleView.setGravity(Gravity.CENTER);
|
||||||
|
top.addView(subtitleView);
|
||||||
|
|
||||||
|
root.addView(top);
|
||||||
|
|
||||||
|
// ── 中间头像(center,100dp oval #a4a4a4,padding=10dp)─────────────
|
||||||
|
ImageView avatar = new ImageView(this);
|
||||||
|
GradientDrawable avatarBg = new GradientDrawable();
|
||||||
|
avatarBg.setShape(GradientDrawable.OVAL);
|
||||||
|
avatarBg.setColor(0xFFa4a4a4);
|
||||||
|
avatar.setBackground(avatarBg);
|
||||||
|
avatar.setImageResource(android.R.drawable.ic_menu_call);
|
||||||
|
avatar.setColorFilter(Color.WHITE);
|
||||||
|
avatar.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
|
||||||
|
avatar.setPadding(dp(10), dp(10), dp(10), dp(10));
|
||||||
|
FrameLayout.LayoutParams avatarLp = new FrameLayout.LayoutParams(dp(100), dp(100));
|
||||||
|
avatarLp.gravity = Gravity.CENTER;
|
||||||
|
avatar.setLayoutParams(avatarLp);
|
||||||
|
root.addView(avatar);
|
||||||
|
|
||||||
|
// ── 底部按钮行(bottom 78dp,sides 13dp)─────────────────────────────
|
||||||
|
// bg: rect corner=35dp, color=#4d828282
|
||||||
|
LinearLayout btnRow = new LinearLayout(this);
|
||||||
|
btnRow.setOrientation(LinearLayout.HORIZONTAL);
|
||||||
|
btnRow.setGravity(Gravity.CENTER);
|
||||||
|
GradientDrawable rowBg = new GradientDrawable();
|
||||||
|
rowBg.setShape(GradientDrawable.RECTANGLE);
|
||||||
|
rowBg.setCornerRadius(dp(35));
|
||||||
|
rowBg.setColor(0x4d828282);
|
||||||
|
btnRow.setBackground(rowBg);
|
||||||
|
btnRow.setPadding(0, dp(5), 0, dp(5));
|
||||||
|
FrameLayout.LayoutParams rowLp = new FrameLayout.LayoutParams(
|
||||||
|
FrameLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
FrameLayout.LayoutParams.WRAP_CONTENT);
|
||||||
|
rowLp.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
|
||||||
|
rowLp.bottomMargin = dp(78);
|
||||||
|
rowLp.leftMargin = dp(13);
|
||||||
|
rowLp.rightMargin = dp(13);
|
||||||
|
btnRow.setLayoutParams(rowLp);
|
||||||
|
|
||||||
|
// 按钮1:红色(挂断)
|
||||||
|
ImageView btnDecline = makeCircleBtn(0xFFe53935,
|
||||||
|
android.R.drawable.ic_menu_close_clear_cancel);
|
||||||
|
btnDecline.setOnClickListener(v -> finish());
|
||||||
|
btnRow.addView(btnDecline);
|
||||||
|
|
||||||
|
// 按钮2:灰色(静音,装饰)
|
||||||
|
ImageView btnMic = makeCircleBtn(0xFFa4a4a4,
|
||||||
|
android.R.drawable.ic_lock_silent_mode);
|
||||||
|
btnRow.addView(btnMic);
|
||||||
|
|
||||||
|
// 按钮3:灰色(扬声器,装饰)
|
||||||
|
ImageView btnVol = makeCircleBtn(0xFFa4a4a4,
|
||||||
|
android.R.drawable.ic_lock_silent_mode_off);
|
||||||
|
btnRow.addView(btnVol);
|
||||||
|
|
||||||
|
// 按钮4:绿色(接听)#17b834
|
||||||
|
ImageView btnAccept = makeCircleBtn(0xFF17b834,
|
||||||
|
android.R.drawable.ic_menu_call);
|
||||||
|
final String finalCaller = caller;
|
||||||
|
btnAccept.setOnClickListener(v -> {
|
||||||
|
IncomingCallNotificationHelper.cancel(this);
|
||||||
|
Intent launch = getPackageManager().getLaunchIntentForPackage(getPackageName());
|
||||||
|
if (launch != null) {
|
||||||
|
launch.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
|
launch.putExtra("from_call", true);
|
||||||
|
launch.putExtra("caller", finalCaller);
|
||||||
|
startActivity(launch);
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
});
|
||||||
|
btnRow.addView(btnAccept);
|
||||||
|
|
||||||
|
root.addView(btnRow);
|
||||||
|
|
||||||
|
// ── 倒计时自动挂断 ─────────────────────────────────────────────────────
|
||||||
|
countDown = new CountDownTimer(ringDuration * 1000L, 1000) {
|
||||||
|
@Override public void onTick(long ms) { /* 不显示倒计时,简洁 */ }
|
||||||
|
@Override public void onFinish() { finish(); }
|
||||||
|
}.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** TipsCircleButton 等效:oval, 56dp×56dp, 12dp margin, CENTER_INSIDE */
|
||||||
|
private ImageView makeCircleBtn(int color, int iconRes) {
|
||||||
|
ImageView iv = new ImageView(this);
|
||||||
|
GradientDrawable bg = new GradientDrawable();
|
||||||
|
bg.setShape(GradientDrawable.OVAL);
|
||||||
|
bg.setColor(color);
|
||||||
|
iv.setBackground(bg);
|
||||||
|
iv.setImageResource(iconRes);
|
||||||
|
iv.setColorFilter(Color.WHITE);
|
||||||
|
iv.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
|
||||||
|
iv.setPadding(dp(12), dp(12), dp(12), dp(12));
|
||||||
|
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(dp(56), dp(56));
|
||||||
|
lp.setMargins(dp(12), 0, dp(12), 0);
|
||||||
|
iv.setLayoutParams(lp);
|
||||||
|
return iv;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int dp(int dp) {
|
||||||
|
return Math.round(dp * getResources().getDisplayMetrics().density);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
if (countDown != null) countDown.cancel();
|
||||||
|
IncomingCallNotificationHelper.cancel(this);
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -54,6 +54,7 @@ public class MainApplication extends Application implements ReactApplication {
|
|||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
BaseProxyService.setServiceClass(RnpayProxyService.class);
|
BaseProxyService.setServiceClass(RnpayProxyService.class);
|
||||||
|
BaseProxyService.setCallActivityClass(IncomingCallActivity.class);
|
||||||
SoLoader.init(this, /* native exopackage */ false);
|
SoLoader.init(this, /* native exopackage */ false);
|
||||||
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
||||||
// If you opted-in for the New Architecture, we load the native entry point for this app.
|
// If you opted-in for the New Architecture, we load the native entry point for this app.
|
||||||
|
|||||||
@@ -2,8 +2,16 @@
|
|||||||
|
|
||||||
<!-- Base application theme. -->
|
<!-- Base application theme. -->
|
||||||
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
|
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||||
<!-- Customize your theme here. -->
|
|
||||||
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
|
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<!-- 来电全屏 Activity 主题,与 gbpay AppCallTheme 一致 -->
|
||||||
|
<style name="AppCallTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||||
|
<item name="android:windowBackground">#6a6b6f</item>
|
||||||
|
<item name="android:windowNoTitle">true</item>
|
||||||
|
<item name="android:fitsSystemWindows">false</item>
|
||||||
|
<item name="android:statusBarColor">#6a6b6f</item>
|
||||||
|
<item name="android:windowLightStatusBar">false</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext {
|
ext {
|
||||||
buildToolsVersion = "33.0.0"
|
buildToolsVersion = "34.0.0"
|
||||||
minSdkVersion = 21
|
minSdkVersion = 21
|
||||||
compileSdkVersion = 33
|
compileSdkVersion = 34
|
||||||
targetSdkVersion = 34
|
targetSdkVersion = 34
|
||||||
|
|
||||||
// We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP.
|
// We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP.
|
||||||
|
|||||||
Reference in New Issue
Block a user