Flutter+Hive应用发布至Play Store遇签名不匹配安装错误
Flutter应用问题:Hive本地存储失效+Release模式安装失败
我已将名为moneyreminder的Flutter应用通过Google Play Console发布至Play Store,该应用使用Hive实现本地数据存储,但数据存储模块无法正常工作。同时在Android Studio中运行release模式时出现安装错误:
adb: failed to install C:\Users\Niklas\StudioProjects\moneyreminder\build\app\outputs\flutter-apk\app.apk: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package com.muellerniklas.moneyreminder signatures do not match previously installed version; ignoring!]
主页面代码
import 'package:flutter/material.dart'; import 'package:debt/colors.dart'; import 'package:debt/add.dart'; import 'package:debt/data.dart'; import 'package:flutter/foundation.dart'; import 'package:hive_flutter/hive_flutter.dart'; late Box box; List<Data>datalist=[]; Future <void> main() async{ WidgetsFlutterBinding.ensureInitialized(); await Hive.initFlutter(); Hive.registerAdapter(DataAdapter()); box = await Hive.openBox("infos"); //wandelt die daten für die Anzeige um Map<dynamic, dynamic> data2 = box.toMap(); //macht aus map liste data2.forEach((key, value) { if(kDebugMode){ Data w =Data (key, value); datalist.add(w); } }); runApp(const MaterialApp( home: debt(), debugShowCheckedModeBanner: false, ));} // ignore: camel_case_types class debt extends StatefulWidget { const debt({Key? key}) : super(key: key); @override _debtState createState() => _debtState(); } // ignore: camel_case_types class _debtState extends State<debt> { Map<String, dynamic> values = {}; String text = 'Text'; double w = 100; double h = 20; Widget quoteTemplate(data){ return ValueListenableBuilder<Box>( valueListenable: Hive.box('infos').listenable(), builder: (context, box, widget) { return Card( margin: const EdgeInsets.fromLTRB(16, 16, 16, 0), child:Row( mainAxisAlignment: MainAxisAlignment.spaceAround, // x Achse crossAxisAlignment: CrossAxisAlignment.center, // y Achse children: <Widget>[ Column( mainAxisAlignment: MainAxisAlignment.spaceAround, // x Achse crossAxisAlignment: CrossAxisAlignment.center,// y Achse children: <Widget>[ Container(alignment: Alignment.center, width: 100, height: h, child: Text( data.people, style: TextStyle( fontSize: 18, color: Colors.grey[600], ) ), ), const SizedBox(height: 6,), Container( alignment: Alignment.center, child: Text( data.money, style: TextStyle( fontSize: 14, color: Colors.grey[800], ) ), ), ], ) ,Container(//delete alignment: Alignment.center, child: TextButton(style: TextButton.styleFrom( ), onPressed: (){ box.delete(data.people); setState(() { Map<dynamic, dynamic> data2 = box.toMap(); datalist=[]; data2.forEach((key, value) { if(kDebugMode){ Data w =Data (key, value); datalist.add(w); } }); }); }, child: const Icon(Icons.delete,color: lightblue,), ), ), Container(//minusbutton alignment: Alignment.center, child: TextButton(style: TextButton.styleFrom(//Minus Butten ), onPressed: (){ var zwischenspeicher = box.get(data.people); double zwischenspeicher2= double.parse(zwischenspeicher) - 1.0; var schulden = zwischenspeicher2.toString(); box.put(data.people,schulden); //Updatet das widget setState(() { Map<dynamic, dynamic> data2 = box.toMap(); datalist=[]; data2.forEach((key, value) { if(kDebugMode){ Data w =Data (key, value); datalist.add(w); } }); }); }, child: const Icon(Icons.remove,color: darkblue,), ), ), Container(//plus Button alignment: Alignment.center, child: TextButton(style: TextButton.styleFrom( ), onPressed: (){ var zwischenspeicher = box.get(data.people); var zwischenspeicher2= double.parse(zwischenspeicher) + 1; var schulden = zwischenspeicher2.toString(); box.put(data.people,schulden); setState(() { Map<dynamic, dynamic> data2 = box.toMap(); datalist=[]; data2.forEach((key, value) { if(kDebugMode){ Data w =Data (key, value); datalist.add(w); } }); }); }, child: const Icon(Icons.add,color: darkbrown,), ), ), ], ), );}); }Widget buttond(){ return Padding( padding: const EdgeInsets.all(8.0), child: Expanded(child: Align( alignment: FractionalOffset.bottomRight, child: FloatingActionButton( onPressed: () { _awaitReturnValueFromSecondScreen(context); }, child: const Icon(Icons.add),backgroundColor: lightbrown, ),),), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBar( backgroundColor: lightblue , title: const Text("Money Reminder"), centerTitle: true, ), body: Padding( padding: const EdgeInsets.all(8.0), child: ListView( children: [ Column( children: datalist.map((data)=> quoteTemplate(data)).toList(), ), ], ), ),bottomNavigationBar: Padding( padding: const EdgeInsets.fromLTRB(20,0,20,10), child: ElevatedButton( onPressed: () { _awaitReturnValueFromSecondScreen(context); }, //child: const Icon(Icons.add,color: Colors.white,), child: const Text('add/edit debt',style: TextStyle(fontSize: 18,fontFamily: "Futura",color: Colors.white),), style: ElevatedButton.styleFrom( backgroundColor:lightbrown,) ) ), ); } void _awaitReturnValueFromSecondScreen(BuildContext context) async { // start the SecondScreen and wait for it to finish with a result final result = await Navigator.push( context, MaterialPageRoute( builder: (context) => const add(), )); // after the SecondScreen result comes back update the Text widget with it setState(() { datalist = result; }); } }
添加页面代码
import 'package:flutter/material.dart'; import 'package:debt/colors.dart'; import 'package:debt/data.dart'; import 'package:flutter/foundation.dart'; import 'package:debt/main.dart'; // ignore: camel_case_types class add extends StatefulWidget { const add({Key? key}) : super(key: key); @override State<add> createState() => _addState(); } // ignore: camel_case_types class _addState extends State<add> { String text = "Text2"; Map<String, dynamic> data = {}; double size = 40; double space = 9; List<Data>datalist=[]; TextEditingController name = TextEditingController(); TextEditingController debt = TextEditingController(); @override Widget build(BuildContext context) { return Scaffold( resizeToAvoidBottomInset: false, appBar: AppBar(title: const Text("add debt"), centerTitle: true,backgroundColor: lightblue,), body: Card( margin: EdgeInsets.fromLTRB(size, size, size, 300), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ SizedBox(width: 1,height: space,), TextField( controller: name, style: const TextStyle(color: Colors.black54), decoration: const InputDecoration( hintText: "Niklas, Peter", labelText: "Person", hintStyle: TextStyle(fontFamily: "Futura",), labelStyle: TextStyle(fontSize: 24, fontFamily: "Futura"), border: UnderlineInputBorder(), fillColor: white, filled: true, ), keyboardType: TextInputType.name, obscureText: false, maxLines: 1, ), SizedBox(width: 1,height: space,), TextField( controller: debt, style: const TextStyle(color: Colors.black54), decoration: const InputDecoration( hintText: "10€", labelText: "Debt", hintStyle: TextStyle(fontFamily: "Futura",), labelStyle: TextStyle(fontSize: 24, fontFamily: "Futura"), border: UnderlineInputBorder(), fillColor: white, filled: true, ), keyboardType: TextInputType.number, obscureText: false, maxLength: 16, maxLines: 1, ), const SizedBox(width: 1,height: 70,), ElevatedButton(onPressed: () async{ var _name = name.text; var _debt = debt.text; var _debt_ = ""; var split = ", "; //damit auch "," und nicht nur ", " als Trennung gilt if (_name.contains(",")){ split =","; } var listevonnamen = _name.split(split); // Wandelt Komma in . um um keine Missverständnisse zu erzeugen //für doppelte Texteingabe mit Komma for(var i = 0;i<listevonnamen.length;i++){ //texteingaben Komma zu . _name = listevonnamen[i]; if(_debt.contains(",")){ for(var f = 0; f<_debt.length; f++){ //geht durch jeden Buchstaben und überprüft ob ein Komma vorhanden ist if (_debt[f]== ","){ _debt_ = _debt_ + "."; } else{ _debt_ = _debt_ + _debt[f]; } } _debt = _debt_ ; } //var valuecheck = data.containsKey("$_name"); var schulden = ""; var zwischenspeicher = ""; double zwischenspeicher2 = 0; bool checker = box.containsKey(_name); //überprüft ob konto schon vorhanden if (checker == false){ data.addAll({_name: _debt}); schulden = _debt; } else { // wiederholung zwischenspeicher = box.get(_name); //addiert alte daten zu neuen zwischenspeicher2= double.parse(zwischenspeicher) + double.parse(_debt) ; schulden = zwischenspeicher2.toString(); } // daten werden gespeichert box.put(_name,schulden);} Map<dynamic, dynamic> data2 = box.toMap(); //macht aus map liste data2.forEach((key, value) { if(kDebugMode){ Data w =Data (key, value); datalist.add(w); } }); _sendDataBack(context); }, child: const Text("Send"), style: ElevatedButton.styleFrom( minimumSize: const Size(400,70), textStyle: const TextStyle(fontSize: 24,), backgroundColor: lightbrown, foregroundColor: Colors.white, alignment: Alignment.center ), ), ] ) ) ); } //daten zurücksenden void _sendDataBack(BuildContext context) { List textToSendBack = datalist; Navigator.pop(context, textToSendBack,); } }
项目还包含其他Hive相关配置文件及Data类文件。
内容的提问来源于stack exchange,提问作者Niklas Müller
相关产品推荐
相关产品推荐

