后台进程;短信发送;删除重复代码;

dyb
戴余标 2 years ago
parent fccaea3567
commit 862f4f351c

@ -0,0 +1 @@
/Users/datang/fvm/versions/2.8.0

@ -0,0 +1,4 @@
{
"flutterSdkVersion": "2.8.0",
"flavors": {}
}

@ -35,7 +35,7 @@ android {
defaultConfig { defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.project_telephony" applicationId "com.example.project_telephony"
minSdkVersion 21 minSdkVersion 23
targetSdkVersion 32 targetSdkVersion 32
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName
@ -56,4 +56,5 @@ flutter {
dependencies { dependencies {
implementation 'org.greenrobot:eventbus:3.1.1' implementation 'org.greenrobot:eventbus:3.1.1'
implementation('com.google.android.exoplayer:exoplayer:2.14.1')
} }

@ -1,217 +0,0 @@
package com.example.project_telephony;
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import android.os.Bundle;
import android.telephony.NeighboringCellInfo;
import java.util.List;
/**
* Interface used to interact with the phone. Mostly this is used by the
* TelephonyManager class. A few places are still using this directly.
* Please clean them up if possible and use TelephonyManager insteadl.
*
* {@hide}
*/
interface ITelephony {
/**
* Dial a number. This doesn't place the call. It displays
* the Dialer screen.
* @param number the number to be dialed. If null, this
* would display the Dialer screen with no number pre-filled.
*/
void dial(String number);
/**
* Place a call to the specified number.
* @param number the number to be called.
*/
void call(String number);
/**
* If there is currently a call in progress, show the call screen.
* The DTMF dialpad may or may not be visible initially, depending on
* whether it was up when the user last exited the InCallScreen.
*
* @return true if the call screen was shown.
*/
boolean showCallScreen();
/**
* Variation of showCallScreen() that also specifies whether the
* DTMF dialpad should be initially visible when the InCallScreen
* comes up.
*
* @param showDialpad if true, make the dialpad visible initially,
* otherwise hide the dialpad initially.
* @return true if the call screen was shown.
*
* @see showCallScreen
*/
boolean showCallScreenWithDialpad(boolean showDialpad);
/**
* End call or go to the Home screen
*
* @return whether it hung up
*/
boolean endCall();
/**
* Answer the currently-ringing call.
*
* If there's already a current active call, that call will be
* automatically put on hold. If both lines are currently in use, the
* current active call will be ended.
*
* TODO: provide a flag to let the caller specify what policy to use
* if both lines are in use. (The current behavior is hardwired to
* "answer incoming, end ongoing", which is how the CALL button
* is specced to behave.)
*
* TODO: this should be a oneway call (especially since it's called
* directly from the key queue thread).
*/
void answerRingingCall();
/**
* Silence the ringer if an incoming call is currently ringing.
* (If vibrating, stop the vibrator also.)
*
* It's safe to call this if the ringer has already been silenced, or
* even if there's no incoming call. (If so, this method will do nothing.)
*
* TODO: this should be a oneway call too (see above).
* (Actually *all* the methods here that return void can
* probably be oneway.)
*/
void silenceRinger();
/**
* Check if we are in either an active or holding call
* @return true if the phone state is OFFHOOK.
*/
boolean isOffhook();
/**
* Check if an incoming phone call is ringing or call waiting.
* @return true if the phone state is RINGING.
*/
boolean isRinging();
/**
* Check if the phone is idle.
* @return true if the phone state is IDLE.
*/
boolean isIdle();
/**
* Check to see if the radio is on or not.
* @return returns true if the radio is on.
*/
boolean isRadioOn();
/**
* Check if the SIM pin lock is enabled.
* @return true if the SIM pin lock is enabled.
*/
boolean isSimPinEnabled();
/**
* Cancels the missed calls notification.
*/
void cancelMissedCallsNotification();
/**
* Supply a pin to unlock the SIM. Blocks until a result is determined.
* @param pin The pin to check.
* @return whether the operation was a success.
*/
boolean supplyPin(String pin);
/**
* Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated
* without SEND (so <code>dial</code> is not appropriate).
*
* @param dialString the MMI command to be executed.
* @return true if MMI command is executed.
*/
boolean handlePinMmi(String dialString);
/**
* Toggles the radio on or off.
*/
void toggleRadioOnOff();
/**
* Set the radio to on or off
*/
boolean setRadio(boolean turnOn);
/**
* Request to update location information in service state
*/
void updateServiceLocation();
/**
* Enable location update notifications.
*/
void enableLocationUpdates();
/**
* Disable location update notifications.
*/
void disableLocationUpdates();
/**
* Enable a specific APN type.
*/
int enableApnType(String type);
/**
* Disable a specific APN type.
*/
int disableApnType(String type);
/**
* Allow mobile data connections.
*/
boolean enableDataConnectivity();
/**
* Disallow mobile data connections.
*/
boolean disableDataConnectivity();
/**
* Report whether data connectivity is possible.
*/
boolean isDataConnectivityPossible();
Bundle getCellLocation();
/**
* Returns the neighboring cell information of the device.
*/
List<NeighboringCellInfo> getNeighboringCellInfo();
int getCallState();
int getDataActivity();
int getDataState();
}

@ -1,180 +1,7 @@
package com.example.project_telephony; package com.example.project_telephony;
import android.Manifest;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.provider.CallLog;
import android.telephony.PhoneStateListener;
import android.telephony.SmsManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.content.ContextCompat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.flutter.embedding.android.FlutterActivity; import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity { public class MainActivity extends FlutterActivity {
private Intent serviceIntent;
private ListView listcalls;
private List<Map<String,Object>> mapList;
//权限申请的请求码
private static final int REQUEST_CODE=0;
@Override
public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
super.onCreate(savedInstanceState, persistentState);
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.SEND_SMS} , 1);
PendingIntent sentPI = PendingIntent.getBroadcast(this.getContext(), 0, new Intent("SMS_SENT"), 0);
PendingIntent deliveredPI = PendingIntent.getBroadcast(this.getContext(), 0, new Intent("SMS_DELIVERED"), 0);
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage("18815060992", null, "1", sentPI, deliveredPI);
onShowCallLog();
}
private void initData()
{
ContentResolver contentResolver=getContentResolver();
//调用query方法传入URI参数即CallLog.Calls.CONTENT_URI
//本节希望读取电话号码与事件两个字段,传入一个包含字段名的数组
Cursor cursor=contentResolver.query(CallLog.Calls.CONTENT_URI,new String[]{CallLog.Calls.NUMBER,CallLog.Calls.DATE},null,
null,null);
mapList=new ArrayList<>();
SimpleDateFormat dateFormat=new SimpleDateFormat("yyy-MM-dd");
while(cursor.moveToNext())
{
Map<String,Object> map=new HashMap<>();
map.put(CallLog.Calls.NUMBER,cursor.getString(0));
map.put(CallLog.Calls.DATE,dateFormat.format(new Date(cursor.getLong(1))));
mapList.add(map);
}
}
private void onShowCallLog() {
if(Build.VERSION.SDK_INT>=23)
{
int checkCALL_LOGPermission= ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CALL_LOG);
if(checkCALL_LOGPermission!= PackageManager.PERMISSION_GRANTED){
//用以申请权限的方法此时使用ActivityCompat类的该方法以便于版本兼容
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_CALL_LOG},REQUEST_CODE);
}else
{
//如果已经获取了相关权限调用initData()与initview方法
initData();
}
}else{
//如果api版本低于23直接调用initData()与initView()方法
initData();
}
}
//申请权限做出响应后的回调函数
public void OnRequestPermissionsResult(int requesCode,String[] permission,int[] grantResults)
{
switch (requesCode)
{
case REQUEST_CODE:
if(grantResults[0]==PackageManager.PERMISSION_GRANTED){
Toast.makeText(this,"获取权限成功",Toast.LENGTH_SHORT).show();
//获取权限成功调用initData()与initView()方法
initData();
}else{
Toast.makeText(this,"获取权限失败",Toast.LENGTH_SHORT).show();
//获取权限失败退出Activity
this.finish();
}
break;
default:
super.onRequestPermissionsResult(requesCode,permission,grantResults);
}
}
@Override
public void configureFlutterEngine(FlutterEngine flutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
serviceIntent = new Intent(MainActivity.this, MyService.class);
new MethodChannel(flutterEngine.getDartExecutor(), "com.example.project_telephony")
.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(@NonNull MethodCall methodCall, @NonNull MethodChannel.Result result) {
if (methodCall.method.equals("startService")) {
startService();
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel("channelid1", "channelname", NotificationManager.IMPORTANCE_HIGH);
manager.createNotificationChannel(notificationChannel);
}
Notification notification = new NotificationCompat.Builder(MainActivity.this, "messages")
.setContentTitle("Project_Telephony")
.setContentText("进程已启动")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.build();
manager.notify(1, notification);
result.success("服务已启动");
}
}
});
new MethodChannel(flutterEngine.getDartExecutor(), "com.example.telephony")
.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
if (call.method.equals("listenService")) {
MyPhoneStateListener phoneListener = new MyPhoneStateListener();
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
telephonyManager.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);
result.success("开始监听");
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
stopService(serviceIntent);
}
private void startService() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(serviceIntent);
} else {
startService(serviceIntent);
}
}
} }

@ -1,44 +0,0 @@
package com.example.project_telephony;
import android.content.Context;
import android.telephony.PhoneStateListener;
import android.telephony.SmsManager;
import android.telephony.TelephonyManager;
import java.util.ArrayList;
import io.flutter.Log;
public class MyPhoneStateListener extends PhoneStateListener {
Context context;
int flag = 0;
@Override
public void onCallStateChanged(int state, String incomingNumber) {
Log.e("PhoneCallState", incomingNumber);
try {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE: // 当前电话处于闲置状态
Log.i("state", "闲置");
if (flag != 0) {
Log.e("state", "发短信给"+incomingNumber);
SmsMassage.sendMess("1","10086");
flag = 0;
}
break;
case TelephonyManager.CALL_STATE_RINGING: // 当前电话处于响铃状态
Log.i("state", "响铃");
flag++;
break;
case TelephonyManager.CALL_STATE_OFFHOOK: // 当前电话处于接听状态
Log.i("state", "接听");
flag++;
break;
}
} catch (Exception e) {
e.printStackTrace();
}
super.onCallStateChanged(state, incomingNumber);
}
}

@ -1,31 +0,0 @@
package com.example.project_telephony;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
public class MyService extends Service {
@Override
public void onCreate() {
super.onCreate();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "messages")
.setContentText("正在后台运行")
.setContentTitle("Flutter后台")
.setSmallIcon(R.drawable.launch_background);
startForeground(101, builder.build());
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}

@ -1,48 +0,0 @@
package com.example.project_telephony;
import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.telephony.SmsManager;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.util.ArrayList;
public class SmsMassage extends Activity {
public static void sendMess(String content, String phone) {
SmsManager manager = SmsManager.getDefault();
manager.sendTextMessage(phone, null, content, null, null);
ArrayList<String> strings = manager.divideMessage(content);
for (int i = 0; i < strings.size(); i++) {
}
}
private void requestPermission() {
if(ContextCompat.checkSelfPermission(SmsMassage.this, Manifest.permission.SEND_SMS)!=
PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(SmsMassage.this,new String[]{
Manifest.permission.SEND_SMS},1);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
Toast.makeText(SmsMassage.this, "申请权限", Toast.LENGTH_LONG).show();
switch(requestCode){
case 1:
if(grantResults.length>0&&grantResults[0]!=PackageManager.PERMISSION_GRANTED){
// showToast("拒绝权限将无法使用程序");
Toast.makeText(SmsMassage.this, "拒绝权限将无法使用程序1111", Toast.LENGTH_LONG).show();
finish();
}
break;
default:
break;
}
}
}

@ -1,28 +1,67 @@
import 'dart:async';
import 'package:call_log/call_log.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:flutter_background_service/flutter_background_service.dart';
import 'package:telephony/telephony.dart'; import 'package:telephony/telephony.dart';
import 'mainProvider.dart';
onBackgroundMessage(SmsMessage message) { onBackgroundMessage(SmsMessage message) {
debugPrint("onBackgroundMessage called"); debugPrint("onBackgroundMessage called");
} }
// void backgroundFetchHeadlessTask(HeadlessTask task) async {
// String taskId = task.taskId; Future<void> main() async {
// bool isTimeout = task.timeout; WidgetsFlutterBinding.ensureInitialized();
// if (isTimeout) { await initializeService();
// // This task has exceeded its allowed running-time.
// // You must stop what you're doing and immediately .finish(taskId)
// print("[BackgroundFetch] Headless task timed-out: $taskId");
// BackgroundFetch.finish(taskId);
// return;
// }
// print('[BackgroundFetch] Headless event received.');
// // Do your work here...
// BackgroundFetch.finish(taskId);
// }
void main() {
runApp(const MyApp()); runApp(const MyApp());
// BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask); }
Future<void> initializeService() async {
final service = FlutterBackgroundService();
await service.configure(
androidConfiguration: AndroidConfiguration(
onStart: onStart,
autoStart: true,
isForegroundMode: true,
),
iosConfiguration: IosConfiguration(
autoStart: true,
onForeground: onStart,
onBackground: onIosBackground,
),
);
}
void onIosBackground() {
WidgetsFlutterBinding.ensureInitialized();
print('FLUTTER BACKGROUND FETCH');
}
void onStart() {
int flag = 0;
String? phoneNum,callState;
WidgetsFlutterBinding.ensureInitialized();
Timer.periodic(const Duration(seconds: 1), (timer) async {
CallState state = await Telephony.instance.callState;
callState=state.name;
print(callState!+"$flag");
if (callState == "IDLE") {
if (flag != 0) {
flag = 0;
final Iterable<CallLogEntry> result = await CallLog.query();
phoneNum = await result.first.number;
print(phoneNum);
Phone.telephony.sendSms(to: phoneNum!, message: "hello",isMultipart:true,);
}
} else if (callState == "RINGING") {
flag++;
} else if (callState == "OFFHOOK") {
flag++;
}
});
}
class Phone{
static Telephony telephony = Telephony.instance;
} }
class MyApp extends StatefulWidget { class MyApp extends StatefulWidget {
@ -34,11 +73,12 @@ class MyApp extends StatefulWidget {
class _MyAppState extends State<MyApp> { class _MyAppState extends State<MyApp> {
String _message = ""; String _message = "";
final telephony = Telephony.instance;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
final service = FlutterBackgroundService();
service.start();
} }
onMessage(SmsMessage message) async { onMessage(SmsMessage message) async {
@ -52,10 +92,11 @@ class _MyAppState extends State<MyApp> {
_message = status == SendStatus.SENT ? "sent" : "delivered"; _message = status == SendStatus.SENT ? "sent" : "delivered";
}); });
} }
Future<void> initPlatformState() async { Future<void> initPlatformState() async {
final bool? result = await telephony.requestPhoneAndSmsPermissions; final bool? result = await Phone.telephony.requestPhoneAndSmsPermissions;
if (result != null && result) { if (result != null && result) {
telephony.listenIncomingSms( Phone.telephony.listenIncomingSms(
onNewMessage: onMessage, onBackgroundMessage: onBackgroundMessage); onNewMessage: onMessage, onBackgroundMessage: onBackgroundMessage);
} }
if (!mounted) return; if (!mounted) return;
@ -71,14 +112,9 @@ class _MyAppState extends State<MyApp> {
body: Column( body: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
MultiProvider(providers: [
ChangeNotifierProvider(
create: (context) => MainProvider(),
)
], child: const Home()),
TextButton( TextButton(
onPressed: () async { onPressed: () async {
telephony.sendSms(to: "10086", message: "1"); Phone.telephony.sendSms(to: "10086", message: "1");
}, },
child: const Text('sms')), child: const Text('sms')),
], ],
@ -88,54 +124,3 @@ class _MyAppState extends State<MyApp> {
} }
} }
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> with WidgetsBindingObserver{
final telephony = Telephony.instance;
int flag = 0;
String? phoneNum;
@override
void initState() {
super.initState();
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
MainProvider provider = Provider.of<MainProvider>(context);
provider.addListener(() { });
}
@override
Widget build(BuildContext context) {
String? sta, data;
MainProvider provider = Provider.of<MainProvider>(context);
sta = provider.st;
data = provider.data;
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'$sta',
style: const TextStyle(fontSize: 30),
),
Text('$data'),
],
),
);
}
}
// void startService() async {
// if (Platform.isAndroid) {
// var methodChannel = const MethodChannel("com.example.project_telephony");
// await methodChannel.invokeMethod("startService");
// }
// }

@ -1,44 +0,0 @@
import 'dart:io';
import 'package:call_log/call_log.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:telephony/telephony.dart';
class MainProvider extends ChangeNotifier {
final telephony = Telephony.instance;
String? st, data, num;
int flag = 0;
String? phoneNum;
callState() async {
CallState state = await telephony.callState;
transState(state.name);
notifyListeners();
}
@override
void addListener(VoidCallback listener) {
super.addListener(listener);
callState();
}
transState(String? callState) async {
if (callState == "IDLE") {
if (flag != 0) {
await getNum();
telephony.sendSms(to: phoneNum!, message: "发送短信内容",isMultipart:true,);
flag = 0;
}
} else if (callState == "RINGING") {
flag++;
} else if (callState == "OFFHOOK") {
flag++;
}
}
getNum() async {
final Iterable<CallLogEntry> result = await CallLog.query();
phoneNum = result.first.number;
}
}

@ -57,6 +57,48 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.5" version: "1.0.5"
device_info_plus:
dependency: "direct main"
description:
name: device_info_plus
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
device_info_plus_linux:
dependency: transitive
description:
name: device_info_plus_linux
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
device_info_plus_macos:
dependency: transitive
description:
name: device_info_plus_macos
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.3"
device_info_plus_platform_interface:
dependency: transitive
description:
name: device_info_plus_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.0+1"
device_info_plus_web:
dependency: transitive
description:
name: device_info_plus_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
device_info_plus_windows:
dependency: transitive
description:
name: device_info_plus_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:
@ -64,11 +106,32 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.2.0"
ffi:
dependency: transitive
description:
name: ffi
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1"
file:
dependency: transitive
description:
name: file
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.2"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_background_service:
dependency: "direct main"
description:
name: flutter_background_service
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.6"
flutter_lints: flutter_lints:
dependency: "direct dev" dependency: "direct dev"
description: description:
@ -81,6 +144,18 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
js:
dependency: transitive
description:
name: js
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.3"
lints: lints:
dependency: transitive dependency: transitive
description: description:
@ -123,6 +198,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.1.0" version: "3.1.0"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
provider: provider:
dependency: "direct main" dependency: "direct main"
description: description:
@ -198,13 +280,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.1" version: "2.1.1"
workmanager: win32:
dependency: "direct main" dependency: transitive
description: description:
name: workmanager name: win32
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.4.1" version: "2.5.2"
sdks: sdks:
dart: ">=2.15.0 <3.0.0" dart: ">=2.15.0 <3.0.0"
flutter: ">=1.16.0" flutter: ">=2.0.0"

@ -34,11 +34,11 @@ dependencies:
# The following adds the Cupertino Icons font to your application. # The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons. # Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2 cupertino_icons: ^1.0.2
telephony: ^0.1.4 telephony: any
provider: ^6.0.3 provider: ^6.0.3
call_log: ^4.0.0 call_log: ^4.0.0
workmanager: any flutter_background_service: any
# background_fetch: ^1.1.0 device_info_plus: any
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

Loading…
Cancel
Save