add of sim changes
All checks were successful
/ mirror (push) Successful in 4s

This commit is contained in:
Bartosz 2024-11-28 20:57:58 +00:00
parent 9cd0c612dd
commit 13376118c3
94 changed files with 2584 additions and 123 deletions

View File

@ -16,3 +16,4 @@ subprojects {
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

View File

@ -1,4 +1,4 @@
org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
android.enableJetifier=true
org.gradle.java.home=/usr/lib/jvm/java-17-openjdk-amd64
org.gradle.java.home=/usr/lib/jvm/java-17-openjdk-17.0.13.0.11-3.fc41.x86_64

View File

@ -1,18 +1,16 @@
// delete_key_pair.dart
import 'package:flutter/material.dart';
class SuppressionPaireClesPage extends StatelessWidget {
const SuppressionPaireClesPage({super.key});
class DeleteKeyPairPage extends StatelessWidget {
const DeleteKeyPairPage({super.key});
void _deleteKeyPair(BuildContext context) {
// key deletion logic (not implemented here)
// Key deletion logic (not implemented here)
// ...
// Show confirmation message
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('La paire de clés a été supprimée.'),
content: Text('The key pair has been deleted.'),
),
);
@ -25,18 +23,18 @@ class SuppressionPaireClesPage extends StatelessWidget {
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Confirmer la Suppression'),
title: const Text('Confirm Deletion'),
content: const Text(
'Êtes-vous sûr de vouloir supprimer la paire de clés ? Cette action est irréversible.'),
'Are you sure you want to delete the key pair? This action is irreversible.'),
actions: [
TextButton(
child: const Text('Annuler'),
child: const Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
),
TextButton(
child: const Text('Supprimer'),
child: const Text('Delete'),
onPressed: () {
Navigator.of(context).pop();
_deleteKeyPair(context);
@ -53,14 +51,14 @@ class SuppressionPaireClesPage extends StatelessWidget {
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
title: const Text('Suppression d\'une Paire de Clés'),
title: const Text('Delete a Key Pair'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
_showConfirmationDialog(context);
},
child: const Text('Supprimer la Paire de Clés'),
child: const Text('Delete Key Pair'),
),
),
);

View File

@ -1,24 +1,22 @@
// export_private_key.dart
import 'package:flutter/material.dart';
import 'dart:typed_data';
import 'dart:convert';
import 'package:pointycastle/export.dart' as crypto;
import 'package:file_picker/file_picker.dart';
class ExportationClePriveePage extends StatefulWidget {
const ExportationClePriveePage({super.key});
class ExportPrivateKeyPage extends StatefulWidget {
const ExportPrivateKeyPage({super.key});
@override
_ExportationClePriveePageState createState() => _ExportationClePriveePageState();
_ExportPrivateKeyPageState createState() => _ExportPrivateKeyPageState();
}
class _ExportationClePriveePageState extends State<ExportationClePriveePage> {
class _ExportPrivateKeyPageState extends State<ExportPrivateKeyPage> {
final TextEditingController _passwordController = TextEditingController();
Future<void> _exportPrivateKey() async {
// Replace with your actual private key retrieval logic
final String privateKeyPem = 'Votre clé privée ici';
final String privateKeyPem = 'Your private key here';
// Get the password from the user input
final password = _passwordController.text;
@ -32,7 +30,7 @@ class _ExportationClePriveePageState extends State<ExportationClePriveePage> {
// Let the user pick a file location
final outputFile = await FilePicker.platform.saveFile(
dialogTitle: 'Enregistrer la clé privée chiffrée',
dialogTitle: 'Save encrypted private key',
fileName: 'private_key_encrypted.aes',
);
@ -44,8 +42,8 @@ class _ExportationClePriveePageState extends State<ExportationClePriveePage> {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Clé Exportée'),
content: const Text('La clé privée chiffrée a été exportée avec succès.'),
title: const Text('Key Exported'),
content: const Text('The encrypted private key has been exported successfully.'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
@ -80,14 +78,14 @@ class _ExportationClePriveePageState extends State<ExportationClePriveePage> {
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
title: const Text('Exportation de la Clé Privée'),
title: const Text('Export Private Key'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
const Text(
'Entrez un mot de passe pour chiffrer la clé privée:',
'Enter a password to encrypt the private key:',
style: TextStyle(color: Colors.white),
),
TextField(
@ -95,14 +93,14 @@ class _ExportationClePriveePageState extends State<ExportationClePriveePage> {
obscureText: true,
style: const TextStyle(color: Colors.white),
decoration: const InputDecoration(
hintText: 'Mot de passe',
hintText: 'Password',
hintStyle: TextStyle(color: Colors.grey),
),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _exportPrivateKey,
child: const Text('Exporter la Clé Privée Chiffrée'),
child: const Text('Export Encrypted Private Key'),
),
],
),

View File

@ -5,11 +5,11 @@ import 'dart:convert';
import 'dart:typed_data';
import 'package:asn1lib/asn1lib.dart';
class GenerationNouvellePaireClesPage extends StatelessWidget {
const GenerationNouvellePaireClesPage({super.key});
class GenerateNewKeyPairPage extends StatelessWidget {
const GenerateNewKeyPairPage({super.key});
Future<Map<String, String>> _generateKeyPair() async {
// key generation logic using pointycastle
// Key generation logic using pointycastle
final keyParams = crypto.RSAKeyGeneratorParameters(
BigInt.parse('65537'),
2048,
@ -94,7 +94,7 @@ class GenerationNouvellePaireClesPage extends StatelessWidget {
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
title: const Text('Génération d\'une Nouvelle Paire de Clés'),
title: const Text('Generate a New Key Pair'),
),
body: Center(
child: ElevatedButton(
@ -104,8 +104,8 @@ class GenerationNouvellePaireClesPage extends StatelessWidget {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Clés Générées'),
content: const Text('La nouvelle paire de clés a été générée avec succès.'),
title: const Text('Keys Generated'),
content: const Text('The new key pair has been generated successfully.'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
@ -115,7 +115,7 @@ class GenerationNouvellePaireClesPage extends StatelessWidget {
),
);
},
child: const Text('Générer une Nouvelle Paire de Clés'),
child: const Text('Generate a New Key Pair'),
),
),
);

View File

@ -1,45 +1,43 @@
// manage_keys_page.dart
import 'package:flutter/material.dart';
import 'package:dialer/features/settings/key/show_public_key_text.dart';
import 'package:dialer/features/settings/key/show_public_key_qr.dart';
import 'package:dialer/features/settings/key/show_public_key_text.dart';
import 'package:dialer/features/settings/key/generate_new_key_pair.dart';
import 'package:dialer/features/settings/key/export_private_key.dart';
import 'package:dialer/features/settings/key/delete_key_pair.dart';
class GestionDeClesPage extends StatelessWidget {
const GestionDeClesPage({super.key});
class KeyManagementPage extends StatelessWidget {
const KeyManagementPage({super.key});
void _navigateToOption(BuildContext context, String option) {
switch (option) {
case 'Affichage de la clé publique en texte':
case 'Display public key as text':
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const AffichageClePubliqueTextePage()),
MaterialPageRoute(builder: (context) => const DisplayPublicKeyTextPage()),
);
break;
case 'Affichage de la clé publique en QR code':
case 'Display public key as QR code':
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const AffichageClePubliqueQRCodePage()),
MaterialPageRoute(builder: (context) => const DisplayPublicKeyQRCodePage()),
);
break;
case 'Génération d\'une nouvelle paire de clés':
case 'Generate a new key pair':
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const GenerationNouvellePaireClesPage()),
MaterialPageRoute(builder: (context) => const GenerateNewKeyPairPage()),
);
break;
case 'Exportation de la clé privée en fichier chiffré par mot de passe (AES 256)':
case 'Export private key to password-encrypted file (AES 256)':
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const ExportationClePriveePage()),
MaterialPageRoute(builder: (context) => const ExportPrivateKeyPage()),
);
break;
case 'Suppression d\'une paire de clés, POPUP d\'avertissement':
case 'Delete a key pair, warning POPUP':
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SuppressionPaireClesPage()),
MaterialPageRoute(builder: (context) => const DeleteKeyPairPage()),
);
break;
default:
@ -51,17 +49,17 @@ class GestionDeClesPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final keyManagementOptions = [
'Affichage de la clé publique en texte',
'Affichage de la clé publique en QR code',
'Génération d\'une nouvelle paire de clés',
'Exportation de la clé privée en fichier chiffré par mot de passe (AES 256)',
'Suppression d\'une paire de clés, POPUP d\'avertissement',
'Display public key as text',
'Display public key as QR code',
'Generate a new key pair',
'Export private key to password-encrypted file (AES 256)',
'Delete a key pair, warning POPUP',
];
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
title: const Text('Gestion de clés'),
title: const Text('Key Management'),
),
body: ListView.builder(
itemCount: keyManagementOptions.length,

View File

@ -1,18 +1,18 @@
import 'package:flutter/material.dart';
import 'package:pretty_qr_code/pretty_qr_code.dart';
class AffichageClePubliqueQRCodePage extends StatelessWidget {
const AffichageClePubliqueQRCodePage({super.key});
class DisplayPublicKeyQRCodePage extends StatelessWidget {
const DisplayPublicKeyQRCodePage({super.key});
@override
Widget build(BuildContext context) {
// Replace with your actual public key retrieval logic
final String publicKey = 'Votre clé publique ici';
final String publicKey = 'Your public key here';
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
title: const Text('Clé Publique en QR Code'),
title: const Text('Public Key in QR Code'),
),
body: Center(
child: PrettyQr(

View File

@ -1,19 +1,17 @@
// show_public_key_text.dart
import 'package:flutter/material.dart';
class AffichageClePubliqueTextePage extends StatelessWidget {
const AffichageClePubliqueTextePage({super.key});
class DisplayPublicKeyTextPage extends StatelessWidget {
const DisplayPublicKeyTextPage({super.key});
@override
Widget build(BuildContext context) {
// Replace with your actual public key retrieval logic
final String publicKey = 'Votre clé publique ici';
final String publicKey = 'Your public key here';
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
title: const Text('Clé Publique en Texte'),
title: const Text('Public Key as Text'),
),
body: Center(
child: Padding(

View File

@ -16,7 +16,7 @@ class SettingsPage extends StatelessWidget {
MaterialPageRoute(builder: (context) => const SettingsCallPage()),
);
break;
case 'Page des comptes téléphoniques':
case 'Page of telephone accounts':
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SettingsAccountsPage()),
@ -25,7 +25,7 @@ class SettingsPage extends StatelessWidget {
case 'Gestion de clés':
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const GestionDeClesPage()),
MaterialPageRoute(builder: (context) => const KeyManagementPage()),
);
break;
// Add more cases for other settings pages
@ -39,8 +39,8 @@ class SettingsPage extends StatelessWidget {
Widget build(BuildContext context) {
final settingsOptions = [
'Calling settings',
'Page des comptes téléphoniques',
'Gestion de clés', // Add the new option here
'Page of telephone accounts',
'Key management',
];
return Scaffold(

View File

@ -1,11 +1,8 @@
// choose_sim.dart
import 'package:flutter/material.dart';
import 'package:sim_data/sim_data.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:mobile_number/mobile_number.dart';
class ChooseSimPage extends StatefulWidget {
const ChooseSimPage({super.key});
const ChooseSimPage({Key? key}) : super(key: key);
@override
_ChooseSimPageState createState() => _ChooseSimPageState();
@ -22,20 +19,27 @@ class _ChooseSimPageState extends State<ChooseSimPage> {
}
Future<void> _fetchSimCards() async {
if (await Permission.phone.request().isGranted) {
try {
final simData = await SimDataPlugin.getSimData();
setState(() {
_simCards = simData.cards;
_selectedSimIndex = 0;
});
} catch (e) {
// Handle error
print('Error fetching SIM data: $e');
try {
bool permissionsGranted = await MobileNumber.hasPhonePermission;
if (!permissionsGranted) {
await MobileNumber.requestPhonePermission;
permissionsGranted = await MobileNumber.hasPhonePermission;
}
} else {
// Permission denied
print('Phone permission denied');
if (permissionsGranted) {
List<SimCard>? simCards = await MobileNumber.getSimCards;
if (simCards != null && mounted) {
setState(() {
_simCards = simCards;
_selectedSimIndex = 0;
});
} else {
print('No SIM cards found');
}
} else {
print('Phone permission denied');
}
} catch (e) {
print('Failed to get SIM cards: $e');
}
}
@ -52,12 +56,12 @@ class _ChooseSimPageState extends State<ChooseSimPage> {
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
title: const Text('Choisir la SIM'),
title: const Text('Choose SIM'),
),
body: _simCards.isEmpty
? const Center(
child: Text(
'Aucune carte SIM trouvée',
'No SIM cards found',
style: TextStyle(color: Colors.white),
),
)
@ -71,7 +75,7 @@ class _ChooseSimPageState extends State<ChooseSimPage> {
style: const TextStyle(color: Colors.white),
),
subtitle: Text(
'Opérateur: ${sim.carrierName}',
'Operator: ${sim.carrierName ?? 'N/A'}',
style: const TextStyle(color: Colors.grey),
),
trailing: Radio<int>(

View File

@ -1,11 +1,9 @@
// settings_accounts.dart
import 'package:flutter/material.dart';
import 'package:dialer/features/settings/sim/choose_sim.dart';
import 'package:dialer/features/settings/sim/sim_parameters.dart';
import 'choose_sim.dart';
import 'sim_parameters.dart';
class SettingsAccountsPage extends StatelessWidget {
const SettingsAccountsPage({super.key});
const SettingsAccountsPage({Key? key}) : super(key: key);
void _navigateToAccountOption(BuildContext context, String option) {
switch (option) {
@ -21,7 +19,6 @@ class SettingsAccountsPage extends StatelessWidget {
MaterialPageRoute(builder: (context) => const SimParametersPage()),
);
break;
// Handle more options if needed
default:
break;
}
@ -47,7 +44,8 @@ class SettingsAccountsPage extends StatelessWidget {
accountOptions[index],
style: const TextStyle(color: Colors.white),
),
trailing: const Icon(Icons.arrow_forward_ios, color: Colors.white),
trailing:
const Icon(Icons.arrow_forward_ios, color: Colors.white),
onTap: () {
_navigateToAccountOption(context, accountOptions[index]);
},

View File

@ -1,11 +1,8 @@
// sim_parameters.dart
import 'package:flutter/material.dart';
import 'package:sim_data/sim_data.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:mobile_number/mobile_number.dart';
class SimParametersPage extends StatefulWidget {
const SimParametersPage({super.key});
const SimParametersPage({Key? key}) : super(key: key);
@override
_SimParametersPageState createState() => _SimParametersPageState();
@ -21,19 +18,27 @@ class _SimParametersPageState extends State<SimParametersPage> {
}
Future<void> _fetchSimParameters() async {
if (await Permission.phone.request().isGranted) {
try {
final simData = await SimDataPlugin.getSimData();
setState(() {
_simCards = simData.cards;
});
} catch (e) {
// Handle error
print('Error fetching SIM data: $e');
try {
bool permissionsGranted = await MobileNumber.hasPhonePermission;
if (!permissionsGranted) {
await MobileNumber.requestPhonePermission;
// Check again if permission is granted
permissionsGranted = await MobileNumber.hasPhonePermission;
}
} else {
// Permission denied
print('Phone permission denied');
if (permissionsGranted) {
List<SimCard>? simCards = await MobileNumber.getSimCards;
if (simCards != null && mounted) {
setState(() {
_simCards = simCards;
});
} else {
print('No SIM cards found');
}
} else {
print('Phone permission denied');
}
} catch (e) {
print('Failed to get SIM cards: $e');
}
}
@ -47,13 +52,12 @@ class _SimParametersPageState extends State<SimParametersPage> {
),
subtitle: Text(
'''
Opérateur: ${sim.carrierName}
Pays: ${sim.countryCode ?? 'N/A'}
MCC: ${sim.mcc ?? 'N/A'}
MNC: ${sim.mnc ?? 'N/A'}
Slot Index: ${sim.slotIndex ?? 'N/A'}
Carrier Name: ${sim.carrierName ?? 'N/A'}
Country Iso: ${sim.countryIso ?? 'N/A'}
Display Name: ${sim.displayName ?? 'N/A'}
''',
Slot Index: ${sim.slotIndex ?? 'N/A'}
Number: ${sim.number ?? 'N/A'}
''',
style: const TextStyle(color: Colors.grey),
),
),
@ -65,12 +69,12 @@ Display Name: ${sim.displayName ?? 'N/A'}
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
title: const Text('Paramètre SIM'),
title: const Text('SIM Parameters'),
),
body: _simCards.isEmpty
? const Center(
child: Text(
'Aucune carte SIM trouvée',
'No SIM cards found',
style: TextStyle(color: Colors.white),
),
)

View File

@ -0,0 +1,59 @@
## 2.1.1
* Fix Android building
## 2.1.0
* Make min sdk to Flutter 3.0.0
## 2.0.0
* Remove null check operator from method ListenPhone
## 1.0.4
* Null safety support
## 1.0.3
* Fix crash because of null value on empty number
## 1.0.2
* Support old Flutter plugin V1
## 1.0.1
* Fix crash related to Android 10
## 1.0.0
* Addded has phone permission
* Added request phone permission
* Added phone permission listener
* Fix bugs
## 0.0.6
* Add sample image.
## 0.0.5
* Add support for dual sim card.
## 0.0.4
* Print exception message on debugging console.
## 0.0.3
* Migrate to AndroidX
## 0.0.2
* Add gt mobile number native code to Android
## 0.0.1
* Initial Release.

View File

@ -0,0 +1,13 @@
Copyright 2023 Amr Eniou
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.

View File

@ -0,0 +1,66 @@
# mobile_number
This is a FLutter Plugin to get the device mobile number.
#### Note: It works for Android only because getting mobile number of sim card is not supported in iOS.
#### Note: If the mobile number is not pre-exist on sim card it will not return te phone number.
## Installation
#### Link on Flutter plugins
https://pub.dev/packages/mobile_number
#### Note:
if you still using depecated FlutterActivty on MainActivity.java
which is import of
- `import io.flutter.app.FlutterActivity;`
not
- `import io.flutter.embedding.android.FlutterActivity;`
then you need to add the following to your MainActivity.java
```
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MobileNumberPlugin.registerWith(registrarFor("com.amorenew.mobile_number.MobileNumberPlugin()"));
}
```
## Usage
#### Check Phone Permission
```await MobileNumber.hasPhonePermission```
#### Request Phone Permission
```await MobileNumber.requestPhonePermission```
#### Listen to widget resume after Phone Permission request
```MobileNumber.listenPhonePermission((isPermissionGranted) {
if (isPermissionGranted) {
//Get mobile number
} else {
//Request Phone Permission
}
});
```
#### Get first sim card number
```Future<String> getMobileNumber() async {
final String mobileNumber = await MobileNumber.mobileNumber;
return mobileNumber;
}
```
#### Get List of sim cards for dual sim cards
```Future<List<SimCard>> geSimCards() async {
final List<SimCard> simCards = await MobileNumber.getSimCards;
return simCards;
}
```
![alt text](https://raw.githubusercontent.com/amorenew/Flutter-Mobile-Number-Plugin/master/sample1.png)

View File

@ -0,0 +1,41 @@
group 'com.amorenew.mobile_number'
version '1.0-SNAPSHOT'
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.2.2'
}
}
rootProject.allprojects {
repositories {
google()
mavenCentral()
}
}
apply plugin: 'com.android.library'
android {
compileSdkVersion 33
namespace "com.amorenew.mobile_number"
defaultConfig {
targetSdkVersion 33
minSdkVersion 21
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
lintOptions {
disable 'InvalidPackage'
}
}
dependencies {
implementation 'androidx.core:core:1.9.0'
// Other dependencies...
}

View File

@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true

View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1 @@
rootProject.name = 'mobile_number'

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.amorenew.mobile_number"> <!-- Package is "com.amorenew.mobile_number" -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"
android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</manifest>

View File

@ -0,0 +1,262 @@
package com.amorenew.mobile_number;
import java.util.HashMap;
import java.util.Map;
class CountryToPhonePrefix {
private static Map<String, String> map = new HashMap<>();
static String prefixFor(String iso2CountryCode) {
String result = map.get(iso2CountryCode.toUpperCase());
if (result == null) {
return "";
}
return result;
}
static {
map.put("AC", "247");
map.put("AD", "376");
map.put("AE", "971");
map.put("AF", "93");
map.put("AG", "1268");
map.put("AI", "1264");
map.put("AL", "355");
map.put("AM", "374");
map.put("AN", "599");
map.put("AO", "244");
map.put("AR", "54");
map.put("AS", "1684");
map.put("AT", "43");
map.put("AU", "61");
map.put("AW", "297");
map.put("AX", "35818");
// map.put("AZ", "37497");
map.put("AZ", "994");
map.put("BA", "387");
map.put("BB", "1246");
map.put("BD", "880");
map.put("BE", "32");
map.put("BF", "226");
map.put("BG", "359");
map.put("BH", "973");
map.put("BI", "257");
map.put("BJ", "229");
map.put("BM", "1441");
map.put("BN", "673");
map.put("BO", "591");
map.put("BR", "55");
map.put("BS", "1242");
map.put("BT", "975");
map.put("BW", "267");
map.put("BY", "375");
map.put("BZ", "501");
map.put("CA", "1");
map.put("CC", "61");
map.put("CD", "243");
map.put("CF", "236");
map.put("CG", "242");
map.put("CH", "41");
map.put("CI", "225");
map.put("CK", "682");
map.put("CL", "56");
map.put("CM", "237");
map.put("CN", "86");
map.put("CO", "57");
map.put("CR", "506");
map.put("CS", "381");
map.put("CU", "53");
map.put("CV", "238");
map.put("CX", "61");
// map.put("CY", "90392");
map.put("CY", "357");
map.put("CZ", "420");
map.put("DE", "49");
map.put("DJ", "253");
map.put("DK", "45");
map.put("DM", "1767");
map.put("DO", "1809"); // and 1829?
map.put("DZ", "213");
map.put("EC", "593");
map.put("EE", "372");
map.put("EG", "20");
map.put("EH", "212");
map.put("ER", "291");
map.put("ES", "34");
map.put("ET", "251");
map.put("FI", "358");
map.put("FJ", "679");
map.put("FK", "500");
map.put("FM", "691");
map.put("FO", "298");
map.put("FR", "33");
map.put("GA", "241");
map.put("GB", "44");
map.put("GD", "1473");
map.put("GE", "995");
map.put("GF", "594");
map.put("GG", "44");
map.put("GH", "233");
map.put("GI", "350");
map.put("GL", "299");
map.put("GM", "220");
map.put("GN", "224");
map.put("GP", "590");
map.put("GQ", "240");
map.put("GR", "30");
map.put("GT", "502");
map.put("GU", "1671");
map.put("GW", "245");
map.put("GY", "592");
map.put("HK", "852");
map.put("HN", "504");
map.put("HR", "385");
map.put("HT", "509");
map.put("HU", "36");
map.put("ID", "62");
map.put("IE", "353");
map.put("IL", "972");
map.put("IM", "44");
map.put("IN", "91");
map.put("IO", "246");
map.put("IQ", "964");
map.put("IR", "98");
map.put("IS", "354");
map.put("IT", "39");
map.put("JE", "44");
map.put("JM", "1876");
map.put("JO", "962");
map.put("JP", "81");
map.put("KE", "254");
map.put("KG", "996");
map.put("KH", "855");
map.put("KI", "686");
map.put("KM", "269");
map.put("KN", "1869");
map.put("KP", "850");
map.put("KR", "82");
map.put("KW", "965");
map.put("KY", "1345");
map.put("KZ", "7");
map.put("LA", "856");
map.put("LB", "961");
map.put("LC", "1758");
map.put("LI", "423");
map.put("LK", "94");
map.put("LR", "231");
map.put("LS", "266");
map.put("LT", "370");
map.put("LU", "352");
map.put("LV", "371");
map.put("LY", "218");
map.put("MA", "212");
map.put("MC", "377");
// map.put("MD", "373533");
map.put("MD", "373");
map.put("ME", "382");
map.put("MG", "261");
map.put("MH", "692");
map.put("MK", "389");
map.put("ML", "223");
map.put("MM", "95");
map.put("MN", "976");
map.put("MO", "853");
map.put("MP", "1670");
map.put("MQ", "596");
map.put("MR", "222");
map.put("MS", "1664");
map.put("MT", "356");
map.put("MU", "230");
map.put("MV", "960");
map.put("MW", "265");
map.put("MX", "52");
map.put("MY", "60");
map.put("MZ", "258");
map.put("NA", "264");
map.put("NC", "687");
map.put("NE", "227");
map.put("NF", "672");
map.put("NG", "234");
map.put("NI", "505");
map.put("NL", "31");
map.put("NO", "47");
map.put("NP", "977");
map.put("NR", "674");
map.put("NU", "683");
map.put("NZ", "64");
map.put("OM", "968");
map.put("PA", "507");
map.put("PE", "51");
map.put("PF", "689");
map.put("PG", "675");
map.put("PH", "63");
map.put("PK", "92");
map.put("PL", "48");
map.put("PM", "508");
map.put("PR", "1787"); // and 1939 ?
map.put("PS", "970");
map.put("PT", "351");
map.put("PW", "680");
map.put("PY", "595");
map.put("QA", "974");
map.put("RE", "262");
map.put("RO", "40");
map.put("RS", "381");
map.put("RU", "7");
map.put("RW", "250");
map.put("SA", "966");
map.put("SB", "677");
map.put("SC", "248");
map.put("SD", "249");
map.put("SE", "46");
map.put("SG", "65");
map.put("SH", "290");
map.put("SI", "386");
map.put("SJ", "47");
map.put("SK", "421");
map.put("SL", "232");
map.put("SM", "378");
map.put("SN", "221");
map.put("SO", "252");
map.put("SR", "597");
map.put("ST", "239");
map.put("SV", "503");
map.put("SY", "963");
map.put("SZ", "268");
map.put("TA", "290");
map.put("TC", "1649");
map.put("TD", "235");
map.put("TG", "228");
map.put("TH", "66");
map.put("TJ", "992");
map.put("TK", "690");
map.put("TL", "670");
map.put("TM", "993");
map.put("TN", "216");
map.put("TO", "676");
map.put("TR", "90");
map.put("TT", "1868");
map.put("TV", "688");
map.put("TW", "886");
map.put("TZ", "255");
map.put("UA", "380");
map.put("UG", "256");
map.put("US", "1");
map.put("UY", "598");
map.put("UZ", "998");
map.put("VA", "379");
map.put("VC", "1784");
map.put("VE", "58");
map.put("VG", "1284");
map.put("VI", "1340");
map.put("VN", "84");
map.put("VU", "678");
map.put("WF", "681");
map.put("WS", "685");
map.put("YE", "967");
map.put("YT", "262");
map.put("ZA", "27");
map.put("ZM", "260");
map.put("ZW", "263");
}}

View File

@ -0,0 +1,248 @@
package com.amorenew.mobile_number;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import org.json.JSONArray;
import java.util.ArrayList;
import java.util.List;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener;
/**
* MobileNumberPlugin
*/
public class MobileNumberPlugin implements FlutterPlugin, ActivityAware, MethodCallHandler, RequestPermissionsResultListener {
private static final int MY_PERMISSIONS_REQUEST_READ_PHONE_STATE = 0;
final String Event_phonePermissionResult = "requestPhonePermission=";
private EventChannel.EventSink permissionEvent;
private Context applicationContext;
private Activity activity;
private TelephonyManager telephonyManager;
private Result result;
private MethodChannel methodChannel;
private EventChannel permissionEventChannel;
/**
* Plugin registration.
*/
public static void registerWith(Registrar registrar) {
final MobileNumberPlugin instance = new MobileNumberPlugin();
instance.onAttachedToEngine(registrar.context(), registrar.messenger(), registrar.activity());
}
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
onAttachedToEngine(flutterPluginBinding.getApplicationContext(), flutterPluginBinding.getBinaryMessenger(), null);
}
private void onAttachedToEngine(Context applicationContext, BinaryMessenger messenger, Activity _activity) {
this.applicationContext = applicationContext;
if(_activity!=null)
this.activity=_activity;
methodChannel = new MethodChannel(messenger, "mobile_number");
methodChannel.setMethodCallHandler(this);
permissionEventChannel = new EventChannel(messenger, "phone_permission_event");
permissionEventChannel.setStreamHandler(new EventChannel.StreamHandler() {
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
permissionEvent = eventSink;
}
@Override
public void onCancel(Object o) {
}
});
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
}
@Override
public void onAttachedToActivity(@NonNull ActivityPluginBinding activityPluginBinding) {
//MobileNumberPlugin.activity = activityPluginBinding.getActivity();
//activityV2 = activityPluginBinding.getActivity();
activity = activityPluginBinding.getActivity();
}
@Override
public void onDetachedFromActivityForConfigChanges() {
}
@Override
public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding activityPluginBinding) {
}
@Override
public void onDetachedFromActivity() {
}
@Override
public void onMethodCall(MethodCall call, Result result) {
this.result = result;
final String method_GetMobileNumber = "getMobileNumber";
final String method_hasPhonePermission = "hasPhonePermission";
final String method_requestPhonePermission = "requestPhonePermission";
switch (call.method) {
case method_GetMobileNumber:
telephonyManager = (TelephonyManager) applicationContext
.getSystemService(Context.TELEPHONY_SERVICE);
getMobileNumber();
break;
case method_hasPhonePermission:
result.success(hasPhonePermission());
break;
case method_requestPhonePermission:
requestPhonePermission();
break;
default:
result.notImplemented();
break;
}
}
private boolean hasPhonePermission() {
if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
return ContextCompat.checkSelfPermission(applicationContext,
Manifest.permission.READ_PHONE_NUMBERS) == PackageManager.PERMISSION_GRANTED;
} else {
return ContextCompat.checkSelfPermission(applicationContext,
Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED;
}
}
private void requestPhonePermission() {
if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
Manifest.permission.READ_PHONE_NUMBERS)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
ActivityCompat.requestPermissions(activity,
new String[]{Manifest.permission.READ_PHONE_NUMBERS}, MY_PERMISSIONS_REQUEST_READ_PHONE_STATE);
}
} else {
if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
Manifest.permission.READ_PHONE_STATE)) {
} else {
ActivityCompat.requestPermissions(activity,
new String[]{Manifest.permission.READ_PHONE_STATE}, MY_PERMISSIONS_REQUEST_READ_PHONE_STATE);
}
}
}
private void getMobileNumber() {
if (!hasPhonePermission()) {
requestPhonePermission();
} else {
// Permission has already been granted
generateMobileNumber();
}
}
@SuppressLint("HardwareIds")
private void generateMobileNumber() {
JSONArray simJsonArray = new JSONArray();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {
for (SubscriptionInfo subscriptionInfo : getSubscriptions()) {
SimCard simCard = new SimCard(telephonyManager, subscriptionInfo);
simJsonArray.put(simCard.toJSON());
}
}
if (simJsonArray.length()==0) {
SimCard simCard = getSingleSimCard();
if (simCard != null) {
simJsonArray.put(simCard.toJSON());
}
}
if (simJsonArray.toString().isEmpty()) {
Log.d("UNAVAILABLE", "No phone number on sim card#3");
result.error("UNAVAILABLE", "No phone number on sim card", null);
} else result.success(simJsonArray.toString());
}
@SuppressLint("HardwareIds")
SimCard getSingleSimCard() {
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_PHONE_NUMBERS) == PackageManager.PERMISSION_DENIED
&& ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_DENIED) {
Log.e("UNAVAILABLE", "No phone number on sim card Permission Denied#2", null);
return null;
} else if (telephonyManager.getLine1Number() == null || telephonyManager.getLine1Number().isEmpty()) {
Log.e("UNAVAILABLE", "No phone number on sim card#2", null);
return null;
}
return new SimCard(telephonyManager);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1)
List<SubscriptionInfo> getSubscriptions() {
final SubscriptionManager subscriptionManager = (SubscriptionManager) activity.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_PHONE_NUMBERS) == PackageManager.PERMISSION_DENIED
&& ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_DENIED) {
Log.e("UNAVAILABLE", "No phone number on sim card Permission Denied#1", null);
return new ArrayList<>();
} else if (subscriptionManager == null) {
Log.e("UNAVAILABLE", "No phone number on sim card#1", null);
return new ArrayList<>();
}
return subscriptionManager.getActiveSubscriptionInfoList();
}
@Override
public boolean onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
// If request is cancelled, the result arrays are empty.
if (requestCode == MY_PERMISSIONS_REQUEST_READ_PHONE_STATE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (permissionEvent != null)
permissionEvent.success(true);
generateMobileNumber();
return true;
} else {
if (permissionEvent != null)
permissionEvent.success(false);
}
}
result.error("PERMISSION", "onRequestPermissionsResult is not granted", null);
return false;
}
}

View File

@ -0,0 +1,73 @@
package com.amorenew.mobile_number;
import android.annotation.SuppressLint;
import android.os.Build;
import android.telephony.SubscriptionInfo;
import android.telephony.TelephonyManager;
import androidx.annotation.RequiresApi;
import org.json.JSONException;
import org.json.JSONObject;
public class SimCard {
private String carrierName = "";
private String displayName = "";
private int slotIndex = 0;
private String number = "";
private String countryIso = "";
private String countryPhonePrefix = "";
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1)
public SimCard(TelephonyManager telephonyManager, SubscriptionInfo subscriptionInfo) {
this.carrierName = subscriptionInfo.getCarrierName().toString();
this.displayName = subscriptionInfo.getDisplayName().toString();
this.slotIndex = subscriptionInfo.getSimSlotIndex();
this.number = subscriptionInfo.getNumber();
if (subscriptionInfo.getCountryIso() != null && !subscriptionInfo.getCountryIso().isEmpty())
this.countryIso = subscriptionInfo.getCountryIso();
else if (telephonyManager.getSimCountryIso() != null)
this.countryIso = telephonyManager.getSimCountryIso();
this.countryPhonePrefix = CountryToPhonePrefix.prefixFor(this.countryIso);
}
@SuppressLint({"MissingPermission", "HardwareIds"})
public SimCard(TelephonyManager telephonyManager) {
if (telephonyManager.getSimOperator() != null)
carrierName = telephonyManager.getSimOperatorName();
if (telephonyManager.getSimOperator() != null)
displayName = telephonyManager.getSimOperatorName();
if (telephonyManager.getSimCountryIso() != null) {
countryIso = telephonyManager.getSimCountryIso();
countryPhonePrefix = CountryToPhonePrefix.prefixFor(countryIso);
}
if (telephonyManager.getLine1Number() != null && !telephonyManager.getLine1Number().isEmpty()) {
if (telephonyManager.getLine1Number().startsWith("0"))
number = countryPhonePrefix + telephonyManager.getLine1Number().substring(1);
number = telephonyManager.getLine1Number();
}
}
// final JSONArray jsonArray = new JSONArray();
JSONObject toJSON() {
JSONObject json = new JSONObject();
try {
json.put("carrierName", carrierName);
json.put("displayName", displayName);
json.put("slotIndex", slotIndex);
json.put("number", number);
json.put("countryIso", countryIso);
json.put("countryPhonePrefix", countryPhonePrefix);
} catch (JSONException e) {
e.printStackTrace();
}
return json;
}
}

View File

@ -0,0 +1,16 @@
# mobile_number_example
Demonstrates how to use the mobile_number plugin.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.

View File

@ -0,0 +1,58 @@
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdk 33
defaultConfig {
applicationId "com.example.mobile_number_example"
minSdkVersion 21
targetSdkVersion 33
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
signingConfig signingConfigs.debug
}
}
lint {
disable 'InvalidPackage'
}
}
flutter {
source '../..'
}
dependencies {
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

View File

@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mobile_number_example">
<!-- Flutter 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,58 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mobile_number_example">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"
android:label="mobile_number_example">
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:windowSoftInputMode="adjustResize"
android:exported="true">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in @style/LaunchTheme). -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" />
<!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame. -->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background" />
<meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true" />
</activity>
<activity
android:name=".EmbeddingV1Activity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
android:hardwareAccelerated="true"
android:theme="@style/LaunchTheme"
android:windowSoftInputMode="adjustResize" />
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>

View File

@ -0,0 +1,14 @@
package com.example.mobile_number_example;
import android.os.Bundle;
import com.amorenew.mobile_number.MobileNumberPlugin;
import io.flutter.app.FlutterActivity;
public class EmbeddingV1Activity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MobileNumberPlugin.registerWith(registrarFor("com.amorenew.mobile_number.MobileNumberPlugin()"));
}
}

View File

@ -0,0 +1,15 @@
package com.example.mobile_number_example;
import io.flutter.embedding.android.FlutterActivity;
public class MainActivity extends FlutterActivity {
// @Override
// public void configureFlutterEngine(FlutterEngine flutterEngine) {
// super.configureFlutterEngine(flutterEngine);
// flutterEngine.getPlugins().add(new com.example.mobile_number.MobileNumberPlugin());
// }
}

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>
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter 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:color/white</item>
</style>
</resources>

View File

@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mobile_number_example">
<!-- Flutter 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,29 @@
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.2.2'
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}

View File

@ -0,0 +1,4 @@
android.enableJetifier=true
android.useAndroidX=true
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true

View File

@ -0,0 +1,6 @@
#Tue May 19 14:57:48 GST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip

View File

@ -0,0 +1,15 @@
include ':app'
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}

View File

@ -0,0 +1 @@
include ':app'

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>8.0</string>
</dict>
</plist>

View File

@ -0,0 +1,2 @@
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"

View File

@ -0,0 +1,2 @@
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"

View File

@ -0,0 +1,84 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def parse_KV_file(file, separator='=')
file_abs_path = File.expand_path(file)
if !File.exists? file_abs_path
return [];
end
generated_key_values = {}
skip_line_start_symbols = ["#", "/"]
File.foreach(file_abs_path) do |line|
next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
plugin = line.split(pattern=separator)
if plugin.length == 2
podname = plugin[0].strip()
path = plugin[1].strip()
podpath = File.expand_path("#{path}", file_abs_path)
generated_key_values[podname] = podpath
else
puts "Invalid plugin specification: #{line}"
end
end
generated_key_values
end
target 'Runner' do
# Flutter Pod
copied_flutter_dir = File.join(__dir__, 'Flutter')
copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework')
copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec')
unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path)
# Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet.
# That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration.
# CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist.
generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig')
unless File.exist?(generated_xcode_build_settings_path)
raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path)
cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR'];
unless File.exist?(copied_framework_path)
FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir)
end
unless File.exist?(copied_podspec_path)
FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir)
end
end
# Keep pod path relative so it can be checked into Podfile.lock.
pod 'Flutter', :path => 'Flutter'
# Plugin Pods
# Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
# referring to absolute paths on developers' machines.
system('rm -rf .symlinks')
system('mkdir -p .symlinks/plugins')
plugin_pods = parse_KV_file('../.flutter-plugins')
plugin_pods.each do |name, path|
symlink = File.join('.symlinks', 'plugins', name)
File.symlink(path, symlink)
pod name, :path => File.join(symlink, 'ios')
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
end
end

View File

@ -0,0 +1,506 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B80C3931E831B6300D905FE /* App.framework */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEBA1CF902C7004384FC /* Flutter.framework */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
CF3B75C9A7D2FA2A4C99F110 /* Frameworks */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
97C146F11CF9000F007C117D /* Supporting Files */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
);
path = Runner;
sourceTree = "<group>";
};
97C146F11CF9000F007C117D /* Supporting Files */ = {
isa = PBXGroup;
children = (
97C146F21CF9000F007C117D /* main.m */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0910;
ORGANIZATIONNAME = "The Chromium Authors";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
97C146F31CF9000F007C117D /* main.m in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = S8QB4VV633;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.mobileNumberExample;
PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.mobileNumberExample;
PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.mobileNumberExample;
PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0910"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>

View File

@ -0,0 +1,6 @@
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
@interface AppDelegate : FlutterAppDelegate
@end

View File

@ -0,0 +1,13 @@
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end

View File

@ -0,0 +1,122 @@
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

View File

@ -0,0 +1,5 @@
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>mobile_number_example</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>

View File

@ -0,0 +1,9 @@
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char* argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

View File

@ -0,0 +1,78 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:mobile_number/mobile_number.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _mobileNumber = '';
List<SimCard> _simCard = <SimCard>[];
@override
void initState() {
super.initState();
MobileNumber.listenPhonePermission((isPermissionGranted) {
if (isPermissionGranted) {
initMobileNumberState();
} else {}
});
initMobileNumberState();
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initMobileNumberState() async {
if (!await MobileNumber.hasPhonePermission) {
await MobileNumber.requestPhonePermission;
return;
}
// Platform messages may fail, so we use a try/catch PlatformException.
try {
_mobileNumber = (await MobileNumber.mobileNumber)!;
_simCard = (await MobileNumber.getSimCards)!;
} on PlatformException catch (e) {
debugPrint("Failed to get mobile number because of '${e.message}'");
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {});
}
Widget fillCards() {
List<Widget> widgets = _simCard
.map((SimCard sim) => Text(
'Sim Card Number: (${sim.countryPhonePrefix}) - ${sim.number}\nCarrier Name: ${sim.carrierName}\nCountry Iso: ${sim.countryIso}\nDisplay Name: ${sim.displayName}\nSim Slot Index: ${sim.slotIndex}\n\n'))
.toList();
return Column(children: widgets);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(
child: Column(
children: <Widget>[
Text('Running on: $_mobileNumber\n'),
fillCards()
],
),
),
),
);
}
}

View File

@ -0,0 +1,64 @@
name: mobile_number_example
description: Demonstrates how to use the mobile_number plugin.
publish_to: 'none'
environment:
sdk: ">=2.12.0 <3.0.0"
flutter: ">=2.0.0"
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
dev_dependencies:
flutter_test:
sdk: flutter
mobile_number:
path: ../
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/assets-and-images/#from-packages
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages

View File

@ -0,0 +1,27 @@
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility that Flutter provides. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
// import 'package:flutter/material.dart';
// import 'package:flutter_test/flutter_test.dart';
// import '../../example/lib/main.dart';
void main() {
// testWidgets('Verify Platform version', (WidgetTester tester) async {
// // Build our app and trigger a frame.
// await tester.pumpWidget(MyApp());
// // Verify that platform version is retrieved.
// expect(
// find.byWidgetPredicate(
// (Widget widget) => widget is Text &&
// widget.data.startsWith('Running on:'),
// ),
// findsOneWidget,
// );
// });
}

View File

@ -0,0 +1,4 @@
#import <Flutter/Flutter.h>
@interface MobileNumberPlugin : NSObject<FlutterPlugin>
@end

View File

@ -0,0 +1,20 @@
#import "MobileNumberPlugin.h"
@implementation MobileNumberPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:@"mobile_number"
binaryMessenger:[registrar messenger]];
MobileNumberPlugin* instance = [[MobileNumberPlugin alloc] init];
[registrar addMethodCallDelegate:instance channel:channel];
}
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
if ([@"getPlatformVersion" isEqualToString:call.method]) {
result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
} else {
result(FlutterMethodNotImplemented);
}
}
@end

View File

@ -0,0 +1,21 @@
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
#
Pod::Spec.new do |s|
s.name = 'mobile_number'
s.version = '0.0.1'
s.summary = 'A new flutter plugin project.'
s.description = <<-DESC
A new flutter plugin project.
DESC
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email@example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
s.ios.deployment_target = '8.0'
end

View File

@ -0,0 +1,65 @@
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:mobile_number/sim_card.dart';
import 'package:mobile_number/widget_lifecycle.dart';
export 'package:mobile_number/sim_card.dart';
export 'package:mobile_number/widget_lifecycle.dart';
class MobileNumber {
static const MethodChannel _channel = const MethodChannel('mobile_number');
static void listenPhonePermission(
Function(bool isPermissionGranted) subscription,
) {
WidgetsBinding.instance.addObserver(
WidgetLifecycle(
resumeCallBack: (() async {
if (await MobileNumber.hasPhonePermission) {
subscription(true);
} else {
subscription(false);
}
}),
),
);
}
static Future<bool> get hasPhonePermission async {
final bool hasPermission =
await _channel.invokeMethod('hasPhonePermission');
return hasPermission;
}
static Future<void> get requestPhonePermission async {
await _channel.invokeMethod('requestPhonePermission');
}
static Future<String>? get mobileNumber async {
final String simCardsJson = await _channel.invokeMethod('getMobileNumber');
if (simCardsJson.isEmpty) {
return '';
}
List<SimCard> simCards = SimCard.parseSimCards(simCardsJson);
if (simCards.isNotEmpty && simCards[0].number != null) {
return simCards[0].countryPhonePrefix! + simCards[0].number!;
} else {
return '';
}
}
static Future<List<SimCard>>? get getSimCards async {
final String simCardsJson = await _channel.invokeMethod('getMobileNumber');
if (simCardsJson.isEmpty) {
return <SimCard>[];
}
List<SimCard> simCards = SimCard.parseSimCards(simCardsJson);
if (simCards.isNotEmpty) {
return simCards;
} else {
return <SimCard>[];
}
}
}

View File

@ -0,0 +1,43 @@
import 'dart:convert';
class SimCard {
final String? carrierName;
final String? displayName;
final int? slotIndex;
final String? number;
final String? countryIso;
final String? countryPhonePrefix;
SimCard({
this.carrierName,
this.displayName,
this.slotIndex,
this.number,
this.countryIso,
this.countryPhonePrefix,
});
factory SimCard.fromMap(Map<String, dynamic> json) => SimCard(
carrierName: json["carrierName"],
displayName: json["displayName"],
slotIndex: json["slotIndex"],
number: json["number"],
countryIso: json["countryIso"],
countryPhonePrefix: json["countryPhonePrefix"],
);
Map<String, dynamic> toMap() => {
"carrierName": carrierName,
"displayName": displayName,
"slotIndex": slotIndex,
"number": number,
"countryIso": countryIso,
"countryPhonePrefix": countryPhonePrefix,
};
static List<SimCard> parseSimCards(String str) =>
List<SimCard>.from(json.decode(str).map((x) => SimCard.fromMap(x)));
static String simCardToJson(List<SimCard> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toMap())));
}

View File

@ -0,0 +1,30 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
class WidgetLifecycle extends WidgetsBindingObserver {
final AsyncCallback? resumeCallBack;
final AsyncCallback? suspendingCallBack;
WidgetLifecycle({
this.resumeCallBack,
this.suspendingCallBack,
});
@override
Future<Null> didChangeAppLifecycleState(AppLifecycleState state) async {
switch (state) {
case AppLifecycleState.resumed:
if (resumeCallBack != null) {
await resumeCallBack!();
}
break;
case AppLifecycleState.inactive:
case AppLifecycleState.paused:
case AppLifecycleState.detached:
if (suspendingCallBack != null) {
await suspendingCallBack!();
}
break;
}
}
}

View File

@ -0,0 +1,9 @@
## This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Mon Jun 03 03:03:49 EET 2019
ndk.dir=D\:\\Programming\\Android\\Tools\\Android_SDK\\ndk-bundle
sdk.dir=D\:\\Programming\\Android\\Tools\\Android_SDK

View File

@ -0,0 +1,23 @@
name: mobile_number
description: A Flutter plugin for fetching the device's mobile number or list sim cards data
version: 2.1.1
homepage: https://github.com/amorenew/Flutter-Mobile-Number-Plugin
environment:
sdk: ">=2.12.0 <3.0.0"
flutter: ">=3.0.0 <4.0.0"
dependencies:
flutter:
sdk: flutter
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
plugin:
platforms:
android:
package: com.amorenew.mobile_number
pluginClass: MobileNumberPlugin

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

@ -0,0 +1,21 @@
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mobile_number/mobile_number.dart';
void main() {
const MethodChannel channel = MethodChannel('mobile_number');
setUp(() {
channel.setMockMethodCallHandler((MethodCall methodCall) async {
return '42';
});
});
tearDown(() {
channel.setMockMethodCallHandler(null);
});
test('getPlatformVersion', () async {
expect(await MobileNumber.mobileNumber, '');
});
}

View File

@ -38,12 +38,13 @@ dependencies:
flutter_contacts: ^1.1.9+2
permission_handler: ^10.2.0 # For handling permissions
cached_network_image: ^3.2.3 # For caching contact images
sim_data: ^0.0.2
pretty_qr_code: ^3.3.0
pointycastle: ^3.4.0
file_picker: ^5.2.5
asn1lib: ^1.0.0
intl_utils: ^2.0.7
mobile_number:
path: packages/mobile_number
dev_dependencies:
flutter_test: