I create compound index:
db.dailyWork.createIndex({"companyId": 1, "salaryMonth":1, "employeeId":1})
and, I RUN command explain's result is good:
db.dailyWork.find({"companyId" : ObjectId("60fe62de551f6014f5ff9af5"),"salaryMonth" : "2022-09"}).explain("executionStats")
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "cowboy.dailyWork",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"companyId" : {
"$eq" : ObjectId("60fe62de551f6014f5ff9af5")
}
},
{
"salaryMonth" : {
"$eq" : "2022-09"
}
}
]
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"companyId" : 1,
"salaryMonth" : 1,
"employeeId" : 1
},
"indexName" : "companyId_1_salaryMonth_1_employeeId_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"companyId" : [ ],
"salaryMonth" : [ ],
"employeeId" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"companyId" : [
"[ObjectId('60fe62de551f6014f5ff9af5'), ObjectId('60fe62de551f6014f5ff9af5')]"
],
"salaryMonth" : [
"[\"2022-09\", \"2022-09\"]"
],
"employeeId" : [
"[MinKey, MaxKey]"
]
}
}
},
"rejectedPlans" : [
{
"stage" : "FETCH",
"filter" : {
"companyId" : {
"$eq" : ObjectId("60fe62de551f6014f5ff9af5")
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"salaryMonth" : 1
},
"indexName" : "salaryMonth_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"salaryMonth" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"salaryMonth" : [
"[\"2022-09\", \"2022-09\"]"
]
}
}
},
{
"stage" : "FETCH",
"filter" : {
"salaryMonth" : {
"$eq" : "2022-09"
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"companyId" : 1
},
"indexName" : "companyId_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"companyId" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"companyId" : [
"[ObjectId('60fe62de551f6014f5ff9af5'), ObjectId('60fe62de551f6014f5ff9af5')]"
]
}
}
}
]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 88078,
"executionTimeMillis" : 183,
"totalKeysExamined" : 88078,
"totalDocsExamined" : 88078,
"executionStages" : {
"stage" : "FETCH",
"nReturned" : 88078,
"executionTimeMillisEstimate" : 151,
"works" : 88079,
"advanced" : 88078,
"needTime" : 0,
"needYield" : 0,
"saveState" : 691,
"restoreState" : 691,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 88078,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 88078,
"executionTimeMillisEstimate" : 30,
"works" : 88079,
"advanced" : 88078,
"needTime" : 0,
"needYield" : 0,
"saveState" : 691,
"restoreState" : 691,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"companyId" : 1,
"salaryMonth" : 1,
"employeeId" : 1,
},
"indexName" : "companyId_1_salaryMonth_1_employeeId_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"companyId" : [ ],
"salaryMonth" : [ ],
"employeeId" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"companyId" : [
"[ObjectId('60fe62de551f6014f5ff9af5'), ObjectId('60fe62de551f6014f5ff9af5')]"
],
"salaryMonth" : [
"[\"2022-09\", \"2022-09\"]"
],
"employeeId" : [
"[MinKey, MaxKey]"
]
},
"keysExamined" : 88078,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
},
"serverInfo" : {
"host" : "izwz9j7ffkk3uyach8aflfz",
"port" : 27017,
"version" : "3.4.10",
"gitVersion" : "078f28920cb24de0dd479b5ea6c66c644f6326e9"
},
"ok" : 1
}
but I get different result from my node server. It's the same query condition:
{
"op": "query",
"ns": "cowboy.dailyWork",
"query": {
"find": "dailyWork",
"filter": {
"$and": [{
"companyId": ObjectId("60fe62de551f6014f5ff9af5")
}, {
"salaryMonth": "2022-09"
}
]
},
"sort": {
"_id": 1
},
"projection": {
"employeeId": 1,
"price": 1,
"amount": 1
},
"returnKey": false,
"showRecordId": false
},
"cursorid": 70514389445,
"keysExamined": 29726623,
"docsExamined": 29726623,
"fromMultiPlanner": true,
"replanned": true,
"numYield": 251263,
"locks": {
"Global": {
"acquireCount": {
"r": NumberLong(502528)
}
},
"Database": {
"acquireCount": {
"r": NumberLong(251264)
}
},
"Collection": {
"acquireCount": {
"r": NumberLong(251264)
}
}
},
"nreturned": 101,
"responseLength": 7476,
"protocol": "op_query",
"millis": 35504,
"planSummary": "IXSCAN { companyId: 1, salaryMonth: 1, employeeId: 1 }",
"execStats": {
"stage": "PROJECTION",
"nReturned": 101,
"executionTimeMillisEstimate": 27861,
"works": 29726623,
"advanced": 101,
"needTime": 29726522,
"needYield": 0,
"saveState": 251264,
"restoreState": 251263,
"isEOF": 0,
"invalidates": 0,
"transformBy": {
"employeeId": 1,
"price": 1,
"amount": 1
},
"inputStage": {
"stage": "FETCH",
"filter": {
"$and": [{
"companyId": {
"$eq": ObjectId("60fe62de551f6014f5ff9af5")
}
}, {
"salaryMonth": {
"$eq": "2022-09"
}
}
]
},
"nReturned": 101,
"executionTimeMillisEstimate": 27387,
"works": 29726623,
"advanced": 101,
"needTime": 29726522,
"needYield": 0,
"saveState": 251264,
"restoreState": 251263,
"isEOF": 0,
"invalidates": 0,
"docsExamined": 29726623,
"alreadyHasObj": 0,
"inputStage": {
"stage": "IXSCAN",
"nReturned": 29726623,
"executionTimeMillisEstimate": 9654,
"works": 29726623,
"advanced": 29726623,
"needTime": 0,
"needYield": 0,
"saveState": 251264,
"restoreState": 251263,
"isEOF": 0,
"invalidates": 0,
"keyPattern": {
"_id": 1
},
"indexName": "_id_",
"isMultiKey": false,
"multiKeyPaths": {
"_id": []
},
"isUnique": true,
"isSparse": false,
"isPartial": false,
"indexVersion": 2,
"direction": "forward",
"indexBounds": {
"_id": ["[MinKey, MaxKey]"]
},
"keysExamined": 29726623,
"seeks": 1,
"dupsTested": 0,
"dupsDropped": 0,
"seenInvalidated": 0
}
}
},
"ts": ISODate("2022-09-30T17:34:34.965Z"),
"client": "127.0.0.1",
"allUsers": [{
"user": "cowboyUser",
"db": "cowboy"
}
],
"user": "cowboyUser#cowboy"
}
but more wired thing is, if the results item less than about 80000, the query is fast, the only different condition is 'salaryMonth', the former one is '2022-09', below is '2020-08'. '2022-09' condition will find 88078 items, but '2022-08' will find 71678 items. These results is not far different, but first query is so slow(27+ sec), the 2rd query just less than 1 sec. The 2rd query as below:
{
"op": "query",
"ns": "cowboy.dailyWork",
"query": {
"find": "dailyWork",
"filter": {
"$and": [{
"companyId": ObjectId("60fe62de551f6014f5ff9af5")
}, {
"salaryMonth": "2022-08"
}
]
},
"sort": {
"_id": 1
},
"projection": {
"employeeId": 1,
"price": 1,
"amount": 1
},
"returnKey": false,
"showRecordId": false
},
"cursorid": 71019107321,
"keysExamined": 71678,
"docsExamined": 71678,
"hasSortStage": true,
"numYield": 563,
"locks": {
"Global": {
"acquireCount": {
"r": NumberLong(1128)
}
},
"Database": {
"acquireCount": {
"r": NumberLong(564)
}
},
"Collection": {
"acquireCount": {
"r": NumberLong(564)
}
}
},
"nreturned": 101,
"responseLength": 7872,
"protocol": "op_query",
"millis": 415,
"planSummary": "IXSCAN { companyId: 1, salaryMonth: 1, employeeId: 1 }",
"execStats": {
"stage": "CACHED_PLAN",
"nReturned": 101,
"executionTimeMillisEstimate": 413,
"works": 101,
"advanced": 101,
"needTime": 0,
"needYield": 0,
"saveState": 564,
"restoreState": 563,
"isEOF": 0,
"invalidates": 0,
"inputStage": {
"stage": "PROJECTION",
"nReturned": 101,
"executionTimeMillisEstimate": 413,
"works": 71781,
"advanced": 101,
"needTime": 71680,
"needYield": 0,
"saveState": 564,
"restoreState": 563,
"isEOF": 0,
"invalidates": 0,
"transformBy": {
"employeeId": 1,
"price": 1,
"amount": 1
},
"inputStage": {
"stage": "SORT",
"nReturned": 101,
"executionTimeMillisEstimate": 413,
"works": 71781,
"advanced": 101,
"needTime": 71680,
"needYield": 0,
"saveState": 564,
"restoreState": 563,
"isEOF": 0,
"invalidates": 0,
"sortPattern": {
"_id": 1
},
"memUsage": 32000792,
"memLimit": 33554432,
"inputStage": {
"stage": "SORT_KEY_GENERATOR",
"nReturned": 71678,
"executionTimeMillisEstimate": 212,
"works": 71680,
"advanced": 71678,
"needTime": 1,
"needYield": 0,
"saveState": 564,
"restoreState": 563,
"isEOF": 1,
"invalidates": 0,
"inputStage": {
"stage": "FETCH",
"nReturned": 71678,
"executionTimeMillisEstimate": 170,
"works": 71679,
"advanced": 71678,
"needTime": 0,
"needYield": 0,
"saveState": 564,
"restoreState": 563,
"isEOF": 1,
"invalidates": 0,
"docsExamined": 71678,
"alreadyHasObj": 0,
"inputStage": {
"stage": "IXSCAN",
"nReturned": 71678,
"executionTimeMillisEstimate": 60,
"works": 71679,
"advanced": 71678,
"needTime": 0,
"needYield": 0,
"saveState": 564,
"restoreState": 563,
"isEOF": 1,
"invalidates": 0,
"keyPattern": {
"companyId": 1,
"salaryMonth": 1,
"employeeId": 1
},
"indexName": "companyId_1_salaryMonth_1_employeeId_1",
"isMultiKey": false,
"multiKeyPaths": {
"companyId": [],
"salaryMonth": [],
"employeeId": []
},
"isUnique": false,
"isSparse": false,
"isPartial": false,
"indexVersion": 2,
"direction": "forward",
"indexBounds": {
"companyId": ["[ObjectId('60fe62de551f6014f5ff9af5'), ObjectId('60fe62de551f6014f5ff9af5')]"],
"salaryMonth": ["[\"2022-08\", \"2022-08\"]"],
"employeeId": ["[MinKey, MaxKey]"]
},
"keysExamined": 71678,
"seeks": 1,
"dupsTested": 0,
"dupsDropped": 0,
"seenInvalidated": 0
}
}
}
}
}
},
"ts": ISODate("2022-09-30T17:52:33.762Z"),
"client": "127.0.0.1",
"allUsers": [{
"user": "cowboyUser",
"db": "cowboy"
}
],
"user": "cowboyUser#cowboy"
}
I have enough RAM, the only different is result items amount. If the result amount more than 80000, the query become very slow. If you know what's going on, please tell me, thanks!
Environment:
mongodb version 3.4.10
Disk data: 140GB
RAM: 64GB
16x cpu
The explain output you've provided does not include the .sort({ "_id": 1 }) clause that is present in your full query. To that end, you should create the following index:
{ "companyId" : 1, "salaryMonth" : 1, "_id": 1 }
This should also help solve the second part of your problem which is seemingly that planning the query itself also seems to be taking some time. We can see in the second query you provided that CACHED_PLAN is present indicating that some of the query planning work was avoided. The index proposed above should help make the query much more efficient overall, which should have the added benefit of making the query planning process faster as well.
I'm having problem with the camera and the android photo gallery. In debug mode it works on the emulator and also on the device. When I generate the APK and install it on the device, the problem occurs. I try to use the camera or select an image the app unexpectedly closes. I assume it's a permission issue. I'm using permission_handler: "^5.1.0+1" and I followed an example I found on the web (https://pub.dev/packages/permission_handler/versions/5.1.0+1).
I can't use the current version because my project is on old Flutter and I had a lot of difficulties to upgrade.
I really need help.
import 'package:flutter/material.dart';
import 'dart:convert';
import 'dart:io';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:http/http.dart' as http;
import 'package:mysongs_v2/app_localizations.dart';
import 'package:mysongs_v2/global.dart';
import 'package:mysongs_v2/models/user.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:shared_preferences/shared_preferences.dart';
class PhotoProfileScreen extends StatefulWidget {
final int userId;
final String photo;
PhotoProfileScreen({Key key, this.userId, this.photo}) : super(key: key);
#override
_PhotoProfileScreenState createState() => _PhotoProfileScreenState();
}
class _PhotoProfileScreenState extends State<PhotoProfileScreen> {
bool _updated = false;
String _link = "";
final _scaffoldKey = GlobalKey<ScaffoldState>();
File _selectedFile;
bool _inProcess = false;
File imageFile;
final picker = ImagePicker();
bool _isReadyToSave = false;
#override
void initState() {
super.initState();
}
Widget getImageWidget() {
if (_selectedFile != null) {
return Image.file(
_selectedFile,
width: 250,
height: 250,
fit: BoxFit.cover,
);
} else {
return Image.asset(
"images/nickfrost.jpg",
width: 250,
height: 250,
fit: BoxFit.cover,
);
}
}
getImage(ImageSource source) async {
// request a user for permission first
this.setState(() {
_inProcess = true;
});
final image = ImagePicker();
final pickedFile = await image.getImage(source: source);
if (pickedFile == null) {
Navigator.pop(context, _updated);
return;
}
final File imageFile = File(pickedFile.path);
if (image != null) {
File cropped = await ImageCropper.cropImage(
sourcePath: imageFile.path,
aspectRatioPresets: [
CropAspectRatioPreset.square,
CropAspectRatioPreset.ratio3x2,
CropAspectRatioPreset.original,
CropAspectRatioPreset.ratio4x3,
CropAspectRatioPreset.ratio16x9
],
androidUiSettings: AndroidUiSettings(
toolbarTitle:
AppLocalizations.of(context).translate("pfs:crop_image"),
toolbarColor: COLOR_BUTTONS,
toolbarWidgetColor: Colors.white,
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false),
iosUiSettings: IOSUiSettings(
minimumAspectRatio: 1.0,
),
);
this.setState(() {
_selectedFile = cropped;
_inProcess = false;
_isReadyToSave = true;
});
} else {
this.setState(() {
_inProcess = false;
_isReadyToSave = false;
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: new AppBar(
title: new Text(
AppLocalizations.of(context).translate("pfs:title"),
),
elevation: 0.0,
backgroundColor: COLOR_MAIN,
),
body: Stack(
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
getImageWidget(),
Container(
padding: EdgeInsets.only(bottom: 8),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new Column(
children: [
new FloatingActionButton(
heroTag: "btnCamera",
onPressed: () async {
Map<Permission, PermissionStatus> statuses = await [
Permission.mediaLibrary,
Permission.storage,
Permission.camera,
Permission.photos,
].request();
print('permissao:');
print(statuses[Permission.camera]);
if (await Permission.camera.isPermanentlyDenied) {
// The user opted to never again see the permission request dialog for this
// app. The only way to change the permission's status now is to let the
// user manually enable it in the system settings.
openAppSettings();
}
getImage(ImageSource.camera);
},
tooltip: AppLocalizations.of(context)
.translate("pfs:new_picture"),
child: Icon(
Icons.add_a_photo,
size: 35,
),
backgroundColor: COLOR_MAIN,
),
new SizedBox(
height: 5,
),
],
),
new Column(
children: [
new FloatingActionButton(
heroTag: "btnGalery",
onPressed: () async {
Map<Permission, PermissionStatus> statuses = await [
Permission.mediaLibrary,
Permission.storage,
Permission.camera,
Permission.photos,
].request();
print('permissao:');
print(statuses[Permission.photos]);
if (await Permission.photos.isPermanentlyDenied) {
// The user opted to never again see the permission request dialog for this
// app. The only way to change the permission's status now is to let the
// user manually enable it in the system settings.
openAppSettings();
}
getImage(ImageSource.gallery);
},
tooltip: AppLocalizations.of(context)
.translate("pfs:select_from_gallery"),
child: Icon(Icons.add_photo_alternate),
backgroundColor: COLOR_MAIN,
),
new SizedBox(
height: 5,
),
],
),
],
),
new Container(
height: 30,
),
new Visibility(
visible: _isReadyToSave,
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Spacer(),
new TextButton.icon(
label: Text(
' ${AppLocalizations.of(context).translate("pfs:cancel")} ',
),
icon: Icon(Icons.cancel),
style: ElevatedButton.styleFrom(
onPrimary: COLOR_BUTTONS,
primary: Colors.white,
padding: const EdgeInsets.all(8.0),
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(18.0),
side: BorderSide(color: COLOR_BUTTONS),
),
),
onPressed: () {
Navigator.pop(context, _updated);
},
),
SizedBox(
width: 20,
),
new TextButton.icon(
label: Text(
' ${AppLocalizations.of(context).translate("pfs:save")} ',
),
icon: Icon(Icons.check),
style: ElevatedButton.styleFrom(
onPrimary: Colors.white,
primary: COLOR_BUTTONS,
padding: const EdgeInsets.all(8.0),
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(18.0),
side: BorderSide(color: COLOR_BUTTONS),
),
),
onPressed: () async {
if (widget.photo == NOHASPHOTO) {
if (SERVER_NAME == '10.0.2.2/api') {
_link =
'http://localhost/api/$FOLDER_IMAGES_PROFILE/${widget.userId}.jpg';
} else {
_link =
'http://$SERVER_NAME/$FOLDER_IMAGES_PROFILE/${widget.userId}.jpg';
}
await updatePhoto(http.Client(), widget.userId,
"${widget.userId}.jpg", _link);
_savePhotoRegister("${widget.userId}.jpg");
}
uploadServer();
final snackBar = SnackBar(
backgroundColor: COLOR_SNACK,
content: Text(
AppLocalizations.of(context)
.translate("pfs:image_saved"),
),
duration: Duration(seconds: 1),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
_updated = true;
Navigator.pop(context, _updated);
},
),
new Spacer(),
],
),
),
],
),
(_inProcess)
? Container(
color: Colors.white,
height: MediaQuery.of(context).size.height * 0.95,
child: Center(
child: CircularProgressIndicator(),
),
)
: Center()
],
),
);
}
name: mysongs_v2
description: A new Flutter project.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.0+1
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
query_params: "^0.6.0"
http: "^0.12.0+3"
quick_actions: "^0.4.0+1"
shared_preferences: "0.5.7+3"
intl: "^0.16.0"
flutter_i18n: "^0.20.1"
provider: "^4.0.1"
flutter_speed_dial: "^1.2.5"
webview_flutter: "^0.3.14+1"
truncate: "^2.1.2"
screen: "^0.0.5"
flutter_reorderable_list: "^0.1.3"
url_launcher: "^5.4.2"
infinite_listview: "^1.0.1+1"
google_fonts: "^1.0.0"
progress_dialog: "^1.2.4"
simple_tooltip: "^0.1.13"
image_picker: "^0.6.7+12"
image_cropper: "^1.2.0"
characters: "^1.0.0"
# location: "^3.0.0"
font_awesome_flutter: "^8.10.1"
flutter_masked_text: "^0.8.0"
share: "^0.6.5+4"
top_snackbar_flutter: "^1.0.2"
material_floating_search_bar: "^0.2.6"
qr_flutter: "^4.0.0"
super_tooltip: "^1.0.1"
permission_handler: "^5.1.0+1"
# 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
dependency_overrides:
intl: "^0.17.0-nullsafety.2"
# 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
assets:
- images/guitar.png
- images/microphone.png
- lang/en.json
- lang/es.json
- lang/pt.json
- images/cover.jpg
- images/nickfrost.jpg
- images/logo_mysongs.png
- images/chords.jpg
- images/text.jpg
# 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
#
fonts:
- family: RobotoMono
fonts:
- asset: fonts/RobotoMono-Regular.ttf
- asset: fonts/RobotoMono-Bold.ttf
weight: 700
- family: CustomIcons
fonts:
- asset: fonts/CustomIcons.ttf
- family: Magneto
fonts:
- asset: fonts/MAGNETOB.TTF
# For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages
Manifest: DEBUG:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="br.com.mysongs">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:name="io.flutter.app.FlutterApplication"
android:label="mysongs_v2"
android:icon="#mipmap/ic_launcher">
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="#style/Theme.AppCompat.Light.NoActionBar"/>
</application>
</manifest>
Manifest: MAIN
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="br.com.mysongs">
<!-- 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="io.flutter.app.FlutterApplication"
android:label="mysongs_v2"
android:usesCleartextTraffic="true"
android:icon="#mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="#style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA" />
<!--
<application
android:name="io.flutter.app.FlutterApplication"
android:label="MySongs"
android:icon="#mipmap/ic_launcher">
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="#style/Theme.AppCompat.Light.NoActionBar"/>
</application> -->
</manifest>
It didn't work as you can see the images below:
Não funciono
The solution to the problem is easy migration of the project to the latest flutter version.
1- Go to the terminal and navigate to the project location. Then update new flutter pub upgrade --major-versions.
2- After this Fix, the code as some of the code will have to change according to new packages but most of it will be the same. I tried it. For me, it takes about 15 min to resolves updates and sometimes packages also guide you through if something is deprecated.
3- Create a new fluter project configure android and ios modules like permission added or other things which are packages requirements.
4- Then run the project. Will be run accordingly both on release and debug. but takes 1 hour. As I know from my experience it is worth it.
Cheers.
Add 'release' block inside the android in app/build.gradle file like give below
buildTypes {
release {
useProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
}
}
**
Create if you dont have, 'app/proguard-rules.pro' file and add the following lines:
**
dontwarn com.yalantis.ucrop**
-keep class com.yalantis.ucrop** { *; }
-keep interface com.yalantis.ucrop** { *; }
-keep class androidx.appcompat.** { *; }
Add Lines to your Manifest: MAIN ..
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Because you provide all permission for the debug mode. if you only provide permission on the main manifest file it will work for both modes.