first
This commit is contained in:
8
android/.gitignore
vendored
Normal file
8
android/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
gradle-wrapper.jar
|
||||
/.gradle
|
||||
/captures/
|
||||
/gradlew
|
||||
/gradlew.bat
|
||||
/local.properties
|
||||
GeneratedPluginRegistrant.java
|
||||
|
||||
77
android/app/build.gradle
Normal file
77
android/app/build.gradle
Normal 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')
|
||||
}
|
||||
BIN
android/app/libs/callmodule-release.aar
Normal file
BIN
android/app/libs/callmodule-release.aar
Normal file
Binary file not shown.
22
android/app/proguard-rules.pro
vendored
Normal file
22
android/app/proguard-rules.pro
vendored
Normal 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
|
||||
7
android/app/src/debug/AndroidManifest.xml
Normal file
7
android/app/src/debug/AndroidManifest.xml
Normal 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>
|
||||
72
android/app/src/main/AndroidManifest.xml
Normal file
72
android/app/src/main/AndroidManifest.xml
Normal 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>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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() {}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
12
android/app/src/main/res/drawable-v21/launch_background.xml
Normal file
12
android/app/src/main/res/drawable-v21/launch_background.xml
Normal 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>
|
||||
12
android/app/src/main/res/drawable/launch_background.xml
Normal file
12
android/app/src/main/res/drawable/launch_background.xml
Normal 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>
|
||||
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 544 B |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 442 B |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 721 B |
BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
18
android/app/src/main/res/values-night/styles.xml
Normal file
18
android/app/src/main/res/values-night/styles.xml
Normal 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>
|
||||
27
android/app/src/main/res/values/styles.xml
Normal file
27
android/app/src/main/res/values/styles.xml
Normal 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>
|
||||
5
android/app/src/main/res/xml/file_paths.xml
Normal file
5
android/app/src/main/res/xml/file_paths.xml
Normal 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>
|
||||
7
android/app/src/profile/AndroidManifest.xml
Normal file
7
android/app/src/profile/AndroidManifest.xml
Normal 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
59
android/build.gradle
Normal 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
|
||||
}
|
||||
3
android/gradle.properties
Normal file
3
android/gradle.properties
Normal file
@@ -0,0 +1,3 @@
|
||||
org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
7
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
7
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal 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
BIN
android/key.jks
Normal file
Binary file not shown.
4
android/key.properties
Normal file
4
android/key.properties
Normal file
@@ -0,0 +1,4 @@
|
||||
storePassword=a123456
|
||||
keyPassword=a123456
|
||||
keyAlias=key0
|
||||
storeFile=../key.jks
|
||||
25
android/settings.gradle
Normal file
25
android/settings.gradle
Normal 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"
|
||||
Reference in New Issue
Block a user