This commit is contained in:
2025-04-09 13:30:50 +08:00
commit a4a995d24c
154 changed files with 9580 additions and 0 deletions

8
android/.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java

77
android/app/build.gradle Normal file
View File

@@ -0,0 +1,77 @@
plugins {
id "com.android.application"
id "kotlin-android"
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id "dev.flutter.flutter-gradle-plugin"
}
def keystorePropertiesFile = rootProject.file("key.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android {
namespace = "com.czg.cashier_reserve"
compileSdk = flutter.compileSdkVersion
// ndkVersion = flutter.ndkVersion
ndkVersion "25.1.8937393"
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = 17
}
defaultConfig {
applicationId = "com.czg.cashierReserve"
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = 1
versionName = "1.0.0"
minSdkVersion 26
targetSdkVersion 33
}
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
debug {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.debug
}
debug {
signingConfig signingConfigs.release
}
}
}
flutter {
source = "../.."
}
configurations.all {
resolutionStrategy {
force 'androidx.core:core-ktx:1.6.0'
}
}
dependencies {
implementation(name:'callmodule-release',ext:'aar')
implementation('com.android.support:appcompat-v7:28.0.0')
}

Binary file not shown.

22
android/app/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,22 @@
# Please add these rules to your existing keep rules in order to suppress warnings.
# This is generated automatically by the Android Gradle plugin.
-dontwarn org.checkerframework.checker.nullness.qual.EnsuresNonNull
-dontwarn org.checkerframework.checker.nullness.qual.RequiresNonNull
-dontwarn org.linphone.core.Address
-dontwarn org.linphone.core.Call$Dir
-dontwarn org.linphone.core.Call$State
-dontwarn org.linphone.core.Call
-dontwarn org.linphone.core.CallLog
-dontwarn org.linphone.core.CallParams
-dontwarn org.linphone.core.Config
-dontwarn org.linphone.core.Core
-dontwarn org.linphone.core.CoreListener
-dontwarn org.linphone.core.CoreListenerStub
-dontwarn org.linphone.core.Factory
-dontwarn org.linphone.core.GlobalState
-dontwarn org.linphone.core.LogCollectionState
-dontwarn org.linphone.core.Reason
-dontwarn org.linphone.core.VideoActivationPolicy
-dontwarn org.linphone.core.tools.Log
-dontwarn org.linphone.core.tools.receiver.BluetoothReceiver
-dontwarn com.kaer.subutil.R$string

View File

@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@@ -0,0 +1,72 @@
<manifest xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- read permissions for external storage -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- installation package permissions -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<!-- write permissions for external storage -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Install/delete permissions, only granted to system apps -->
<uses-permission android:name="android.permission.INSTALL_PACKAGES"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.DELETE_PACKAGES"
tools:ignore="ProtectedPermissions" />
<application
android:label="银收客订餐"
android:name=".CzgApplication"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<!-- Provider -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>

View File

@@ -0,0 +1,36 @@
package com.czg.cashier_reserve;
import android.content.Context;
import io.flutter.plugin.common.BinaryMessenger;
public class ContextHolder {
private static ContextHolder instance;
private Context context;
private BinaryMessenger binaryMessenger;
private ContextHolder() {}
public static ContextHolder getInstance() {
if (instance == null) {
instance = new ContextHolder();
}
return instance;
}
public void setContext(Context context) {
this.context = context;
}
public Context getContext() {
return context;
}
public void setBinaryMessenger(BinaryMessenger binaryMessenger) {
this.binaryMessenger = binaryMessenger;
}
public BinaryMessenger getBinaryMessenger() {
return binaryMessenger;
}
}

View File

@@ -0,0 +1,13 @@
package com.czg.cashier_reserve;
import cn.kaer.callmodule.KeSdk;
import io.flutter.Log;
import io.flutter.app.FlutterApplication;
public class CzgApplication extends FlutterApplication {
@Override
public void onCreate() {
super.onCreate();
}
}

View File

@@ -0,0 +1,64 @@
package com.czg.cashier_reserve;
import android.os.Bundle;
import androidx.annotation.NonNull;
import com.czg.cashier_reserve.call.YJCoreListenerStub;
import com.czg.cashier_reserve.channel.ChannelManager;
import cn.kaer.callmodule.CoreImpl;
import cn.kaer.callmodule.CoreListener;
import cn.kaer.callmodule.KeSdk;
import io.flutter.Log;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
public class MainActivity extends FlutterActivity {
private CoreListener coreListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getFlutterEngine()!= null && getFlutterEngine().getDartExecutor().getBinaryMessenger()!= null) {
Log.i("MainActivity","onCreate +++ " + this);
} else {
Log.e("MainActivity", "FlutterEngine or BinaryMessenger is null, cannot setup EventChannel.");
}
coreListener = new YJCoreListenerStub();
}
@Override
protected void onResume() {
super.onResume();
CoreImpl.getCore().addListener(coreListener);
}
@Override
protected void onPause() {
super.onPause();
CoreImpl.getCore().removeListener(coreListener);
}
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
Log.i("MainActivity","configureFlutterEngine +++ " + this);
ContextHolder.getInstance().setContext(this);
ContextHolder.getInstance().setBinaryMessenger(flutterEngine.getDartExecutor().getBinaryMessenger());
KeSdk.get().init(new KeSdk.Builder().setContext(this)//必选
.setClz(MainActivity.class)//可选 设置拉起通话页面
.setPstnIncomingDelay(2000)//可选 设置有线振铃延迟时间默认1500
.setAutoAnswerByHookoff(true)//可选 设置来电摘手柄自动接听默认false
.setRingPlayAuto(true)//可选 设置来电自动播放铃声默认true
.setPstnRingType(0)//可选 pstn设置铃声 0系统铃声 1和弦铃声
.setAutoTermByHookon(true)//可选 设置放手柄自动挂断默认false
.setAutoChangeChannelByHookoff(true));//可选 设置通话中摘手柄自动切换到手柄通道默认false
ChannelManager.createChannel(flutterEngine.getDartExecutor().getBinaryMessenger());
}
}

View File

@@ -0,0 +1,91 @@
package com.czg.cashier_reserve.call;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.provider.CallLog;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.czg.cashier_reserve.ContextHolder;
import com.czg.cashier_reserve.channel.EventChannelManager;
import org.json.JSONArray;
import org.json.JSONObject;
import java.text.SimpleDateFormat;
import java.util.Date;
import cn.kaer.callmodule.ctrl.CallController;
import cn.kaer.callmodule.exceptions.CallException;
import io.flutter.Log;
public class CallManager {
private static final String[] columns = {CallLog.Calls.CACHED_NAME// 通话记录的联系人
, CallLog.Calls.NUMBER// 通话记录的电话号码
, CallLog.Calls.DATE// 通话记录的日期
, CallLog.Calls.DURATION// 通话时长
, CallLog.Calls.TYPE};// 通话类型}
public static void loadCallLog() {
Context mainActivityContext = ContextHolder.getInstance().getContext();
Log.i("CallManager","loadCallLog -- " + mainActivityContext);
@SuppressLint("Recycle") Cursor cursor = mainActivityContext.getContentResolver().query(CallLog.Calls.CONTENT_URI,
columns, null, null, null);
JSONArray callLogArray = new JSONArray();
assert cursor != null;
Log.i("CallManager","cursor count:" + cursor.getCount());
while (cursor.moveToNext()) {
@SuppressLint("Range") String name = cursor.getString(cursor.getColumnIndex(CallLog.Calls.CACHED_NAME)); //姓名
@SuppressLint("Range") String number = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER)); //号码
@SuppressLint("Range") long dateLong = cursor.getLong(cursor.getColumnIndex(CallLog.Calls.DATE)); //获取通话日期
@SuppressLint("SimpleDateFormat") String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(dateLong));
@SuppressLint("SimpleDateFormat") String time = new SimpleDateFormat("HH:mm").format(new Date(dateLong));
@SuppressLint("Range") int duration = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.DURATION));//获取通话时长,值为多少秒
@SuppressLint("Range") int type = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.TYPE)); //获取通话类型1.呼入2.呼出3.未接
// @SuppressLint("SimpleDateFormat") String dayCurrent = new SimpleDateFormat("dd").format(new Date());
// @SuppressLint("SimpleDateFormat") String dayRecord = new SimpleDateFormat("dd").format(new Date(dateLong));
JSONObject callLog = new JSONObject();
try {
callLog.put("name", name);
callLog.put("number", number);
callLog.put("date", date);
callLog.put("duration", duration);
callLog.put("type", type);
callLog.put("time", time);
} catch (Exception e) {
e.printStackTrace();
}
callLogArray.put(callLog);
}
Log.i("CallManager", "callLogArray: " + callLogArray);
Intent broad = new Intent(EventChannelManager.Action.GET_CALL_LOG_FINISH);
broad.putExtra("callLog", callLogArray.toString());
mainActivityContext.sendBroadcast(broad);
}
public static void acceptCall() {
try {
CallController.get().answer();
} catch (CallException e) {
e.printStackTrace();
}
}
public static void rejectCall() {
try {
CallController.get().term();
} catch (CallException e) {
e.printStackTrace();
}
}
public static void endCall() {}
}

View File

@@ -0,0 +1,41 @@
package com.czg.cashier_reserve.call;
import android.content.Context;
import android.content.Intent;
import com.czg.cashier_reserve.ContextHolder;
import com.czg.cashier_reserve.channel.EventChannelManager;
import com.kaer.subutil.contact.ContactBean;
import com.kaer.subutil.contact.ContactUtil;
import org.json.JSONObject;
import cn.kaer.callmodule.Call;
import cn.kaer.callmodule.CoreListenerStub;
import cn.kaer.callmodule.ctrl.BaseController;
import io.flutter.Log;
public class YJCoreListenerStub extends CoreListenerStub {
public void onCallStateChanged(BaseController var1, Call var2, Call.State var3, String var4) {
ContactBean contactInfo = ContactUtil.getContactInfo(ContextHolder.getInstance().getContext(), var2.getRemoteNumber());
Log.i("YJCoreListenerStub", "onCallStateChanged +++ " + var3);
JSONObject callInfo = new JSONObject();
try {
callInfo.put("state", var3);
callInfo.put("number", var2.getRemoteNumber());
callInfo.put("name", contactInfo.getcName());
callInfo.put("region", contactInfo.getRegion());
} catch (Exception e) {
e.printStackTrace();
}
Log.i("YJCoreListenerStub", "onCallStateChanged: " + callInfo);
Context mainActivityContext = ContextHolder.getInstance().getContext();
Intent broad = new Intent(EventChannelManager.Action.CALL_STATUS_CHANGE);
broad.putExtra("callStatus", callInfo.toString());
mainActivityContext.sendBroadcast(broad);
}
}

View File

@@ -0,0 +1,10 @@
package com.czg.cashier_reserve.channel;
import io.flutter.plugin.common.BinaryMessenger;
public class ChannelManager {
public static void createChannel(BinaryMessenger messenger) {
MessageChannel.addMessageChannel(messenger);
EventChannelManager.addEventChannel(messenger);
}
}

View File

@@ -0,0 +1,18 @@
package com.czg.cashier_reserve.channel;
public class ChannelNames {
public static final String BASE_NAME = "com.czg.cashier_reserve/";
public static final String GET_CALL_LOG = "getCallLog";
public static final String CALL_LOG_CALLBACK = "callLogCallback";
public static final String CALL_STATUS_CHANGE = "callStatusChange";
public static final String ACCEPT_CALL = "acceptCall";
public static final String REJECT_CALL = "rejectCall";
public static final String END_CALL = "endCall";
public static String getChannelName(String name) {
return BASE_NAME + name;
}
}

View File

@@ -0,0 +1,118 @@
package com.czg.cashier_reserve.channel;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import androidx.annotation.RequiresApi;
import com.czg.cashier_reserve.ContextHolder;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.flutter.Log;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.EventChannel;
public class EventChannelManager {
public static Map<String, BroadcastReceiver> receiverMap = new HashMap<>();
public static List<BroadcastReceiver> broadcastReceiverList = new ArrayList<>();
public static void addEventChannel(BinaryMessenger messenger) {
getCallLogCallback(messenger);
callStatusChange(messenger);
}
public static void callStatusChange(BinaryMessenger messenger) {
if (messenger == null) {
return;
}
EventChannel callStatusChannel = new EventChannel(messenger, ChannelNames.getChannelName(ChannelNames.CALL_STATUS_CHANGE));
callStatusChannel.setStreamHandler(new EventChannel.StreamHandler() {
private BroadcastReceiver broadCast;
@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
broadCast = EventChannelManager.getBroadCast(eventSink);
Context context = ContextHolder.getInstance().getContext();
IntentFilter intentFilter = new IntentFilter(EventChannelManager.Action.CALL_STATUS_CHANGE);
context.registerReceiver(broadCast, intentFilter, Context.RECEIVER_NOT_EXPORTED);
receiverMap.put(EventChannelManager.Action.CALL_STATUS_CHANGE, broadCast);
}
@Override
public void onCancel(Object o) {
Context context = ContextHolder.getInstance().getContext();
context.unregisterReceiver(broadCast);
broadcastReceiverList.remove(broadCast);
broadCast = null;
}
});
}
public static void getCallLogCallback(BinaryMessenger messenger) {
if (messenger == null) {
return;
}
EventChannel callLogChannel = new EventChannel(messenger, ChannelNames.getChannelName(ChannelNames.CALL_LOG_CALLBACK));
callLogChannel.setStreamHandler(new EventChannel.StreamHandler() {
private BroadcastReceiver broadCast;
@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
broadCast = EventChannelManager.getBroadCast(eventSink);
Context context = ContextHolder.getInstance().getContext();
IntentFilter intentFilter = new IntentFilter(EventChannelManager.Action.GET_CALL_LOG_FINISH);
context.registerReceiver(broadCast, intentFilter, Context.RECEIVER_NOT_EXPORTED);
receiverMap.put(EventChannelManager.Action.GET_CALL_LOG_FINISH, broadCast);
}
@Override
public void onCancel(Object o) {
Context context = ContextHolder.getInstance().getContext();
context.unregisterReceiver(broadCast);
broadcastReceiverList.remove(broadCast);
broadCast = null;
}
});
}
public static BroadcastReceiver getBroadCast(EventChannel.EventSink eventSink) {
BroadcastReceiver b = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Action.GET_CALL_LOG_FINISH.equals(action)) {
String extra = intent.getStringExtra("callLog");
eventSink.success(extra);
} if (Action.CALL_STATUS_CHANGE.equals(action)) {
String extra = intent.getStringExtra("callStatus");
eventSink.success(extra);
} else {
eventSink.error("没有该事件", null, null);
}
}
};
broadcastReceiverList.add(b);
return b;
}
// 这里假设Action是一个定义了相关常量的类示例如下你可以根据实际情况调整
public static class Action {
public static final String GET_CALL_LOG_FINISH = ChannelNames.BASE_NAME + "get_call_log_finish";
public static final String CALL_STATUS_CHANGE = ChannelNames.BASE_NAME + "call_status_change";
}
}

View File

@@ -0,0 +1,83 @@
package com.czg.cashier_reserve.channel;
import com.czg.cashier_reserve.call.CallManager;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodChannel;
public class MessageChannel {
public static void addMessageChannel(BinaryMessenger messenger) {
callLogChannel(messenger);
acceptCallChannel(messenger);
rejectCallChannel(messenger);
endCallChannel(messenger);
}
public static void callLogChannel(BinaryMessenger messenger) {
if (messenger == null) {
return;
}
MethodChannel methodChannel = new MethodChannel(messenger, ChannelNames.getChannelName(ChannelNames.GET_CALL_LOG));
methodChannel.setMethodCallHandler((call, result) -> {
System.out.println("call.method: " + call.method);
if (call.method.equals(ChannelNames.GET_CALL_LOG)) {
System.out.println("加载通话记录");
result.success(null);
CallManager.loadCallLog();
};
});
}
public static void acceptCallChannel(BinaryMessenger messenger) {
if (messenger == null) {
return;
}
MethodChannel methodChannel = new MethodChannel(messenger, ChannelNames.getChannelName(ChannelNames.ACCEPT_CALL));
methodChannel.setMethodCallHandler((call, result) -> {
System.out.println("call.method: " + call.method);
if (call.method.equals(ChannelNames.ACCEPT_CALL)) {
System.out.println("接听电话");
result.success(null);
CallManager.acceptCall();
}
});
}
public static void rejectCallChannel(BinaryMessenger messenger) {
if (messenger == null) {
return;
}
MethodChannel methodChannel = new MethodChannel(messenger, ChannelNames.getChannelName(ChannelNames.REJECT_CALL));
methodChannel.setMethodCallHandler((call, result) -> {
System.out.println("call.method: " + call.method);
if (call.method.equals(ChannelNames.REJECT_CALL)) {
System.out.println("拒接电话");
result.success(null);
CallManager.rejectCall();
}
});
}
public static void endCallChannel(BinaryMessenger messenger) {
if (messenger == null) {
return;
}
MethodChannel methodChannel = new MethodChannel(messenger, ChannelNames.getChannelName(ChannelNames.END_CALL));
methodChannel.setMethodCallHandler((call, result) -> {
System.out.println("call.method: " + call.method);
if (call.method.equals(ChannelNames.END_CALL)) {
System.out.println("结束通话");
result.success(null);
CallManager.endCall();
}
});
}
}

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
<style name="DialerDigit" parent="@android:style/TextAppearance.Medium">
<item name="android:padding">5dp</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">match_parent</item>
<item name="android:layout_centerInParent">true</item>
<item name="android:soundEffectsEnabled">false</item>
<!-- <item name="android:background">@drawable/keyboard_numb_bg</item>-->
</style>
</resources>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path path="Android/data/com.czg.cashier_reserve/" name="files_root" />
<external-path path="." name="external_storage_root" />
</paths>

View File

@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

59
android/build.gradle Normal file
View File

@@ -0,0 +1,59 @@
allprojects {
repositories {
flatDir {
dirs 'libs'
}
google()
mavenCentral()
}
}
subprojects {
afterEvaluate { project ->
// if (project.plugins.hasPlugin('com.android.library') || project.plugins.hasPlugin('com.android.application')) {
// println "project: ${project.name} Namespace get: ${project.android.namespace}"
// def packageName = project.android.namespace ?: project.android.defaultConfig.applicationId ?: project.android.sourceSets.main.manifest.srcFile.text.find(/package="([^"]*)"/) ?: project.group
//// project.android.namespace = packageName
//// println "Namespace set to: ${packageName} for project: ${project.name}"
//
// // 如果包名不包含 "com.baidu",则设置命名空间
// if (packageName.contains('com.baidu')) {
// println "Skipping namespace setting for project ${project.name} as the package name contains 'com.baidu' or 'isar_flutter_libs'"
// } else {
// project.android.namespace = packageName
// println "Namespace set to: ${packageName} for project: ${project.name}"
// }
// }
if (project.plugins.hasPlugin("com.android.application") ||
project.plugins.hasPlugin("com.android.library")) {
project.android {
compileSdkVersion 34
buildToolsVersion "34.0.0"
}
}
if (project.hasProperty("android")) {
project.android {
if (namespace == null) {
namespace project.group
}
}
}
}
// ============
project.buildDir = "${rootProject.buildDir}/${project.name}"
// project.evaluationDependsOn(":app")
}
rootProject.buildDir = "../build"
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
//}
//subprojects {
project.evaluationDependsOn(":app")
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

View File

@@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
android.enableJetifier=true

View File

@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

BIN
android/key.jks Normal file

Binary file not shown.

4
android/key.properties Normal file
View File

@@ -0,0 +1,4 @@
storePassword=a123456
keyPassword=a123456
keyAlias=key0
storeFile=../key.jks

25
android/settings.gradle Normal file
View File

@@ -0,0 +1,25 @@
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.3.2" apply false
id "org.jetbrains.kotlin.android" version "2.0.20" apply false
}
include ":app"