Flutter 第三方一些應(yīng)用及打包

1、Flutter 報錯 Could not create task ‘xxx‘.this and base files have different roots
1、問題場景:此問題會出現(xiàn)在你的項目路徑不在 C 盤(系統(tǒng)盤)或是不在 flutter sdk 所在盤符下。正常在 flutter 項目中運行沒有問題,會出現(xiàn)在將 flutter 以 Android 項目打開。
看報錯信息,屬于是文件存在在了兩個路徑,它不知道咋整。可能是編譯Android 項目時,默認會將第三方的緩存在系統(tǒng)盤。
2、解決辦法:
方法一、把項目復(fù)制到和 flutter 相同的目錄下,重新打開項目即可
方法二、a、在項目盤符下新建文件夾,正常命名(別整中文和特殊符號,flutter_pub_cache我覺得就不錯),然后打開環(huán)境變量,新建或編輯系統(tǒng)環(huán)境變量,輸入PUB_CACHE,然后將你剛才創(chuàng)建的文件路徑填進去。
b、重啟電腦
c、打開flutter 項目,flutter pub get,
d、打開 Android 項目,本次編譯可能時間較長
原文鏈接:https://blog.csdn.net/LoveShadowing/article/details/132210526
2、shared_preferences
本地存儲工具類,不限制string bool int list及l(fā)ist<Map>等結(jié)構(gòu)

class Storage {
  static setData(String key, dynamic value) async {
    SharedPreferences pref = await SharedPreferences.getInstance();
    pref.setString(key, json.encode(value));
  }

  static getData(String key) async {
    SharedPreferences pref = await SharedPreferences.getInstance();
    String? data = pref.getString(key);
    return json.decode(data!);
  }

  static removeData(String key) async {
    SharedPreferences pref = await SharedPreferences.getInstance();
    return pref.remove(key);
  }
}

其他基本使用

class _SharePreferenecesPagerState extends State<SharePreferenecesPager> {
  final Future<SharedPreferences> _prefs = SharedPreferences.getInstance();

  _saveData() async {
    final prefs = await _prefs;
    prefs.setString("username", "張三");
    prefs.setInt("age", 20);

    List<String> userinfo = ["張三", "李四", "王五"];
    prefs.setStringList("userinfo", userinfo);

    List<Map> newsList = [
      {"title": "我是一個標題"},
      {"title": "我是二個標題"},
    ];
    prefs.setString("newsList", json.encode(newsList));
  }

  _getData() async {
    final prefs = await _prefs;
    String? username = prefs.getString("username");
    print(username);

    int? age = prefs.getInt("age");
    print(age);

    List<String>? list = prefs.getStringList("userinfo");
    print(list);
    print(list![0]);

    //獲取List<Map>
    String? newsList = prefs.getString("newsList");
    var tempData = json.decode(newsList!);
    print(tempData[0]);
    print(tempData[0]["title"]);
  }

  _removeData() async {
    final prefs = await _prefs;
    prefs.remove("username");
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Title'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: _saveData,
              child: const Text('保存數(shù)據(jù)'),
            ),
            const SizedBox(height: 10),
            ElevatedButton(
              onPressed: _getData,
              child: const Text('獲取數(shù)據(jù)'),
            ),
            const SizedBox(height: 10),
            ElevatedButton(
              onPressed: _removeData,
              child: const Text('清除數(shù)據(jù)'),
            ),
            const SizedBox(height: 10),
            ElevatedButton(
                onPressed: () async {
                  Storage.setData("username", "李四");
                },
                child: const Text("設(shè)置String")),
            const SizedBox(height: 10),
            ElevatedButton(
                onPressed: () async {
                  var username = await Storage.getData("username");
                  // print(username as String);
                },
                child: const Text("獲取String")),
            const SizedBox(height: 10),
            ElevatedButton(
                onPressed: () {
                  List<Map> list = [
                    {"title": "一個新聞111", "author": "itying"},
                    {"title": "一個新聞", "author": "itying"},
                    {"title": "一個新聞", "author": "itying"},
                  ];
                  Storage.setData("newslist", list);
                },
                child: const Text("設(shè)置List")),
            const SizedBox(height: 10),
            ElevatedButton(
                onPressed: () async {
                  var list = await Storage.getData("newslist");
                },
                child: const Text("獲取List數(shù)據(jù)")),
            const SizedBox(height: 10),
            ElevatedButton(
                onPressed: () async {
                  Storage.setData("num", 123.4);
                },
                child: const Text("設(shè)置num數(shù)據(jù)")),
            const SizedBox(height: 10),
            ElevatedButton(
                onPressed: () async {
                  var num = await Storage.getData("num");
                },
                child: const Text("獲取num數(shù)據(jù)")),
            const SizedBox(height: 10),
            ElevatedButton(
                onPressed: () async {
                  Storage.setData("flag", false);
                },
                child: const Text("設(shè)置bool數(shù)據(jù)")),
            const SizedBox(height: 10),
            ElevatedButton(
                onPressed: () async {
                  var flag = await Storage.getData("flag");
                },
                child: const Text("獲取bool數(shù)據(jù)")),
          ],
        ),
      ),
    );
  }
}

3、barcode_scan2可以實現(xiàn)掃描條形碼、二維碼
Android配置
<uses-permission android:name="android.permission.CAMERA" />
Ios里面的配置

<dict>
<!-- ... -->
<key>NSCameraUsageDescription</key>
<string>Camera permission is required for barcode scanning.</string>
<!-- ... -->
</dict>

基本使用

class _ScanPagerState extends State<ScanPager> {
  late String scanData = "內(nèi)容";
  void doBarcodeScan() async {
    var options = const ScanOptions(
// set the options
        autoEnableFlash: true,
        strings: {
          'cancel': '取消',
          'flash_on': '打開Flash',
          'flash_off': '關(guān)閉Flash',
        });
    var result = await BarcodeScanner.scan(options: options);
    print(result.type); // The result type (barcode, cancelled, failed)
    print(result.rawContent); // The barcode content
    print(result.format); // The barcode format (as enum)
    print(result .formatNote); // If a unknown format was scanned this field contains a
    setState(() {
      scanData = result.rawContent;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("掃一掃")),
      body: Center(
        child: Column(children: [
          Text(scanData),
          const SizedBox(height: 20),
          ElevatedButton(onPressed: doBarcodeScan, child: const Text("掃一掃"))
        ]),
      ),
    );
  }
}

4、地圖定位實現(xiàn)

import 'package:flutter/material.dart';
import 'dart:async';
import 'package:amap_flutter_location/amap_flutter_location.dart';
import 'package:amap_flutter_location/amap_location_option.dart';
import 'package:permission_handler/permission_handler.dart';

class GaodeMapLocation extends StatefulWidget {
  const GaodeMapLocation({super.key});

  @override
  State<GaodeMapLocation> createState() => _GaodeMapLocationState();
}

class _GaodeMapLocationState extends State<GaodeMapLocation> {
  String _latitude = ""; //緯度
  String _longitude = ""; //經(jīng)度

  //監(jiān)聽定位
  late StreamSubscription<Map<String, Object>> _locationListener;
  //實例化插件
  final AMapFlutterLocation _locationPlugin = AMapFlutterLocation();

  @override
  void initState() {
    super.initState();

    /// 動態(tài)申請定位權(quán)限
    requestPermission();
    AMapFlutterLocation.setApiKey(
        "d21b99823c36665d5a2c1a06ee4a8186", "ios ApiKey");

    ///注冊定位結(jié)果監(jiān)聽
    _locationListener = _locationPlugin
        .onLocationChanged()
        .listen((Map<String, Object> result) {
      setState(() {
        print(result);
        _latitude = result["latitude"].toString();
        _longitude = result["longitude"].toString();
      });
    });
  }

  @override
  void dispose() {
    super.dispose();

    ///移除定位監(jiān)聽
    if (null != _locationListener) {
      _locationListener.cancel();
    }

    ///銷毀定位
    if (null != _locationPlugin) {
      _locationPlugin.destroy();
    }
  }

  ///設(shè)置定位參數(shù)
  void _setLocationOption() {
    if (null != _locationPlugin) {
      AMapLocationOption locationOption = new AMapLocationOption();

      ///是否單次定位
      locationOption.onceLocation = true;

      ///是否需要返回逆地理信息
      locationOption.needAddress = true;

      ///逆地理信息的語言類型
      locationOption.geoLanguage = GeoLanguage.DEFAULT;

      locationOption.desiredLocationAccuracyAuthorizationMode =
          AMapLocationAccuracyAuthorizationMode.ReduceAccuracy;

      locationOption.fullAccuracyPurposeKey = "AMapLocationScene";

      ///設(shè)置Android端連續(xù)定位的定位間隔
      locationOption.locationInterval = 2000;

      ///設(shè)置Android端的定位模式<br>
      ///可選值:<br>
      ///<li>[AMapLocationMode.Battery_Saving]</li>
      ///<li>[AMapLocationMode.Device_Sensors]</li>
      ///<li>[AMapLocationMode.Hight_Accuracy]</li>
      locationOption.locationMode = AMapLocationMode.Hight_Accuracy;

      ///設(shè)置iOS端的定位最小更新距離<br>
      locationOption.distanceFilter = -1;

      ///設(shè)置iOS端期望的定位精度
      /// 可選值:<br>
      /// <li>[DesiredAccuracy.Best] 最高精度</li>
      /// <li>[DesiredAccuracy.BestForNavigation] 適用于導(dǎo)航場景的高精度 </li>
      /// <li>[DesiredAccuracy.NearestTenMeters] 10米 </li>
      /// <li>[DesiredAccuracy.Kilometer] 1000米</li>
      /// <li>[DesiredAccuracy.ThreeKilometers] 3000米</li>
      locationOption.desiredAccuracy = DesiredAccuracy.Best;

      ///設(shè)置iOS端是否允許系統(tǒng)暫停定位
      locationOption.pausesLocationUpdatesAutomatically = false;

      ///將定位參數(shù)設(shè)置給定位插件
      _locationPlugin.setLocationOption(locationOption);
    }
  }

  ///開始定位
  void _startLocation() {
    if (null != _locationPlugin) {
      ///開始定位之前設(shè)置定位參數(shù)
      _setLocationOption();
      _locationPlugin.startLocation();
    }
  }

  /// 動態(tài)申請定位權(quán)限
  void requestPermission() async {
    // 申請權(quán)限
    bool hasLocationPermission = await requestLocationPermission();
    if (hasLocationPermission) {
      print("定位權(quán)限申請通過");
    } else {
      print("定位權(quán)限申請不通過");
    }
  }

  ///  申請定位權(quán)限  授予定位權(quán)限返回true, 否則返回false
  Future<bool> requestLocationPermission() async {
    //獲取當前的權(quán)限
    var status = await Permission.location.status;
    if (status == PermissionStatus.granted) {
      //已經(jīng)授權(quán)
      return true;
    } else {
      //未授權(quán)則發(fā)起一次申請
      status = await Permission.location.request();
      if (status == PermissionStatus.granted) {
        return true;
      } else {
        return false;
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("地理定位演示"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            //  latitude: 36.570091461155336, longitude: 109.5080830206976
            //
            Text("緯度:$_latitude"),
            Text("經(jīng)度:$_longitude"),
            const SizedBox(height: 20),
            ElevatedButton(
              child: const Text('開始定位'),
              onPressed: () {
                _startLocation();
              },
            ),
          ],
        ),
      ),
    );
  }
}

5、支付寶支付

class _AlipayPagerState extends State<AlipayPager> {
  _doAliPay() async {
    Tobias tobias = Tobias();
    var response = await Dio().get("https://agent.itying.com/alipay/");
    var aliPayResult = await tobias.pay(response.data);
    print(aliPayResult); //跳轉(zhuǎn)到訂單列表
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Title'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(onPressed: _doAliPay, child: const Text("支付寶支付"))
          ],
        ),
      ),
    );
  }
}

6、APP升級安裝

class _AppVersionPageState extends State<AppVersionPage> {
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    getPackageInfo();
    getAppPath();
  }

  //彈出Dialog  備用
  void showUpgradesDialog() async {
    await showDialog(
        context: context,
        builder: (context) {
          return AlertDialog(
            title: const Text("更新APP提示!"),
            content: const Text("發(fā)現(xiàn)新的版本,新版本修復(fù)了如下bug 是否更新!"),
            actions: <Widget>[
              ElevatedButton(
                child: const Text("否"),
                onPressed: () {
                  Navigator.pop(context, 'Cancle');
                },
              ),
              ElevatedButton(
                child: const Text("是"),
                onPressed: () {
                  Navigator.pop(context, 'Ok');
                },
              )
            ],
          );
        });
  }

  //獲取版本號
  getPackageInfo() async {
    PackageInfo packageInfo = await PackageInfo.fromPlatform();
    String appName = packageInfo.appName;
    String packageName = packageInfo.packageName;
    String version = packageInfo.version; //1.0.0
    String buildNumber = packageInfo.buildNumber; //1
  }

//獲取路徑
  getAppPath() async {
    Directory? directory = await getExternalStorageDirectory();
    //   /storage/emulated/0/Android/data/com.example.flutter_demo/files
    String storageDirectory = directory!.path;
  }

  //檢查權(quán)限
  Future<bool> checkPermission() async {
    if (Theme.of(context).platform == TargetPlatform.android) {
      final status = await Permission.storage.status;
      if (status != PermissionStatus.granted) {
        final result = await Permission.storage.request();
        if (result == PermissionStatus.granted) {
          return true;
        }
      } else {
        return true;
      }
    }
    return false;
  }

  //下載打開文件
  downLoad() async {
    var permission = await checkPermission();
    if (permission) {
      final directory = await getExternalStorageDirectory();
      String localPath = directory!.path;
      String appName = "aaa.apk";
      String savePath = "$localPath/$appName";
      String apkUrl = "https://jd.itying.com/jdshop.apk";

      ///參數(shù)一 文件的網(wǎng)絡(luò)儲存URL
      ///參數(shù)二 下載的本地目錄文件
      ///參數(shù)三 下載監(jiān)聽
      Dio dio = Dio();
      await dio.download(apkUrl, savePath,
          onReceiveProgress: (received, total) {
        if (total != -1) {
          ///當前下載的百分比例
          print((received / total * 100).toStringAsFixed(0) + "%");
        }
      });
      print(savePath);
      await OpenFilex.open(savePath,
          type: "application/vnd.android.package-archive");
    } else {
      print("沒有權(quán)限");
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: downLoad,
        child: const Icon(Icons.arrow_downward),
      ),
      appBar: AppBar(
        title: const Text("app升級演示"),
      ),
      body: const Text("app升級演示"),
    );
  }
}

7、微信 登錄、分享、支付

class _WeixinPaySharePagerState extends State<WeixinPaySharePager> {
  Fluwx fluwx = Fluwx();
  String text = "share text from fluwx"; //分享的文字
  // WeChatScene scene = WeChatScene.session; //分享給好友
  WeChatScene scene = WeChatScene.timeline; //分享到朋友圈
  @override
  void initState() {
    super.initState();
    //初始化fluwx插件
    fluwx.registerApi(
        appId: "wx5881fa2638a2ca60",
        //universalLink 只針對ios
        universalLink: "https://www.itying.com/flutter/");
    //監(jiān)聽微信支付返回的結(jié)果
    fluwx.addSubscriber((response) {
      if (response is WeChatPaymentResponse) {
        setState(() {
          print("pay :${response.isSuccessful}");
        });
      }
    });
    //監(jiān)聽微信登錄
    fluwx.addSubscriber((response) async {
      if (response is WeChatAuthResponse) {
        setState(() async {
          print("state :${response.state} \n code:${response.code}");
          var apiUrl =
              'http://agent.itying.com/wxpay/getUserInfo.php?code=${response.code}';
          var userinfo = await Dio().get(apiUrl);
          Map result = json.decode(userinfo.data);
          print(result);
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('WeixinPay'),
        ),
        body: Center(
            child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              child: const Text('微信支付'),
              onPressed: () async {
                var apiUrl = 'http://agent.itying.com/wxpay/';
                //鏈接自己服務(wù)器獲取到data然后調(diào)用微信pay方法
                var myPayInfo = await Dio().get(apiUrl);
                Map<String, dynamic> result = json.decode(myPayInfo.data);
                fluwx.pay(
                    which: Payment(
                  appId: result['appid'].toString(),
                  partnerId: result['partnerid'].toString(),
                  prepayId: result['prepayid'].toString(),
                  packageValue: result['package'].toString(),
                  nonceStr: result['noncestr'].toString(),
                  timestamp: result['timestamp'],
                  sign: result['sign'].toString(),
                ));
              },
            ),
            const SizedBox(height: 10),
            ElevatedButton(
              child: const Text('微信登錄'),
              onPressed: () {
                fluwx
                    .authBy(
                        which: NormalAuth(
                      scope: 'snsapi_userinfo',
                      state: 'wechat_sdk_demo_test',
                    ))
                    .then((data) {});
              },
            ),
            const SizedBox(height: 10),
            ElevatedButton(
              child: const Text('微信分享文字'),
              onPressed: () {
                fluwx.share(WeChatShareTextModel(text, scene: scene));
              },
            ),
            const SizedBox(height: 10),
            ElevatedButton(
              child: const Text('微信分享 圖文信息'),
              onPressed: () {
                var model = WeChatShareWebPageModel(
                  "https://www.baidu.com",
                  title: "百度官網(wǎng)",
                  thumbnail: WeChatImage.network(
                      "https://www.itying.com/images/201906/goods_img/1120_P_1560842352183.png"),
                  scene: scene,
                );
                fluwx.share(model);
              },
            )
          ],
        )));
  }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容