Android真机无法加载Google Sheets数据问题求助
Android真机无法连接Google Sheets,模拟器正常的排查与解决
我开发了一款Android应用,可将数据录入并存储至Google Sheets。在模拟器中运行时一切正常,能录入新数据且表格显示正常,但编译安装到真机后,数据无法加载、无法录入,应用始终处于加载状态。修改过Kotlin代码及Gradle配置,问题仍未解决。
相关Dart代码如下:
import 'package:gsheets/gsheets.dart'; class GoogleSheetsApi { // create credentials static const _credentials = r''' { "type": "service_account", "project_id": "fortunaapp1", "private_key_id": "50d7c550a7125c82dc99e3481f3441d8453bec68", "private_key": "-----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCUKlkegBFThU+Y rUv0hIGyMR9Qna47+/63VBg0iSeZerszCdcaE3sVi7Jsde3OtM6716Cv9Xfz0nm+ ru7GYkMEHYLfx5cLHKKSW8AjmOVFNaiYZG1cgyR31LfvrAgnGChxNfgYu3dr24ae LFO2GPsmBxQwob+bhwQgevkBfw9/DYCwqf9XA7e4EeoMQKskzcrKANRjVzz15A0u P4y+c0JqFTqazYcU6xlrP7avB1Bu/Bjarz2U64/++pz+Bj7mv5sZWcivOhhcJN+Q lQKVWEvDAWDlO7/lGbfI5mCjl9L56VsGZU4YjBcKkAQepVP6Vthn1ji07jAcarZ4 BEVieVYXAgMBAAECggEAKqTnooossnO/nYtfPaC3rYBK6YqAn94fCUfocZJ6Ncfn wkBWSziJKAHdmC73A5Pxnonow0wsup39EV9K9QlKDZCq3tqUxAt5VROYQQacEmfn vvjEqyhJoj20tQQ4Enx3A2KLph6qt/3miHbsnxAglOjbrEWZnttk2i5apc4auS/L BfD+EtBnHW7UDNIcEGo1X2GU47FL0f5IV8lJH77SshiOfYM1QCL5SuDuWCqo+mWS lRZEJFWH83hH7/UEr/aO1oLj67twylvQtqjuBekt+1bJyVsQB8BeMPZwQMOMUbiQ G73u0eil2fMCRmQJtJZePkZWhR1LBNrWNRavqDbQZQKBgQDKUPaphatXrlzBv+Cg FXcEtuo8KRh6FrQmzLG6kufb3L8iGs9ta3QqQS1JyUBWisJrL0itRemjlrnACJwe wXOpRdjDLPYYa/dadxOpRop1+8gJDCgcQ1+aCKyWvjoEWeRlkDR3Ypp3eEQdIfvX viFdpeQgBfpvjgEocLVV/hweJQKBgQC7ewAM2d5ik/4WFTQGOKC1pQHW61Cz/js/ jee8bW/Uf8nC1UvLujkMHX6cW3BUxmTBgm3bActr74O7rxQqfNv3L6dzhx6U63CV oWtMf4SDqv9gOEkgqli33nEa1En1BC59vWNvFaj9YQ89WKlnDfYutlju+kPiunSB qKVRI2OYiwKBgHa0EkVcfC+xyhKTtgO3FGHbwIsTwZzAfWrWZuEFGKzTVAF6oYGd rkasfxnvzqP4PiINWCLyBidJZCrb4l3ZOzdyF8BMPQgPMM4PV6XWEZ8v3yoPy+jp TspdlIXNjtTGuU8t0NrLK740/iHpso3erEz57GMtnsadFujXWE3gDjdRAoGBAIAk 63zdMebZVvPLHFsgO6DMnzxCbVAJ9n9TRFED0EtD6SlV10/yAmoogtDmoxoe3OFz gBkQ2fT1qmoPmk4MN+F13hPWCG4rmzF7Orb39iB1McaX0kwUgz1yOobnEYH6kLh7 Scq02GQQAnWg83EwFtQI6TK3Ns1zOo0hM5YJBVtPAoGBAJonEAcUG3Vz9EGzDOUA +0Ju7edU6iXhVN8oTEFUPAh7KpqwvfRXdjBAPvf9AW2wm1TIZSpqLwZ3L62m8nQb pCXa5XZE/mOAxorJNHu/HvD2xGttn3yAC0y9a3QI0zf2wXkfE2o/vuwLifwRnJvw aMmn/UhoRJertqcGpN7GTIQh -----END PRIVATE KEY----- ", "client_email": "fortuna@fortunaapp1.iam.gserviceaccount.com", "client_id": "118121372819582547029", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/fortuna%40fortunaapp1.iam.gserviceaccount.com" } '''; // set up & connect to the spreadsheet static final _spreadsheetId = '1_om4BImQtpn3SjehwztKosEvmHQx9cRHQRrZeJkWKfY'; static final _gsheets = GSheets(_credentials); static Worksheet? _worksheet; // some variables to keep track of.. static int numberOfTransactions = 0; static List<List<dynamic>> currentTransactions = []; static bool loading = true; // initialise the spreadsheet! Future init() async { final ss = await _gsheets.spreadsheet(_spreadsheetId); _worksheet = ss.worksheetByTitle('Sheet1'); countRows(); } // count the number of notes static Future countRows() async { while ((await _worksheet!.values .value(column: 1, row: numberOfTransactions + 1)) != '') { numberOfTransactions++; } // now we know how many notes to load, now let's load them! loadTransactions(); } // load existing notes from the spreadsheet static Future loadTransactions() async { if (_worksheet == null) return; for (int i = 1; i < numberOfTransactions; i++) { final String dataNama = await _worksheet!.values.value(column: 1, row: i + 1); final String dataPaspor = await _worksheet!.values.value(column: 2, row: i + 1); final String dataSponsor = await _worksheet!.values.value(column: 3, row: i + 1); final String dataTanggal = await _worksheet!.values.value(column: 4, row: i + 1); if (currentTransactions.length < numberOfTransactions) { currentTransactions.add([ dataNama, dataPaspor, dataSponsor, dataTanggal, ]); } } print(currentTransactions); // this will stop the circular loading indicator loading = false; } // insert a new transaction static Future insert( String nama, String paspor, String sponsor, String tanggal) async { if (_worksheet == null) return; numberOfTransactions++; currentTransactions.add([ nama, paspor, sponsor, tanggal, ]); await _worksheet!.values.appendRow([ nama, paspor, sponsor, tanggal, ]); } }
排查与解决步骤
1. 网络权限检查
确保AndroidManifest.xml中添加了必要的网络权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Android 9及以上版本默认限制明文流量,Google Sheets API使用HTTPS无需额外配置,但如果有自定义域名需配置network_security_config.xml。
2. 服务账号与Spreadsheet权限验证
- 确认目标Google Sheets已共享给代码中的
client_email(fortuna@fortunaapp1.iam.gserviceaccount.com),权限至少设为编辑者。 - 登录Google Cloud控制台,检查对应项目是否启用了Google Sheets API,且服务账号未被限制API访问权限。
3. 添加异常处理,避免加载状态卡死
原代码未处理任何网络或API异常,一旦请求失败会导致loading一直为true。修改关键方法添加异常捕获:
修改init方法:
Future init() async { try { final ss = await _gsheets.spreadsheet(_spreadsheetId); _worksheet = ss.worksheetByTitle('Sheet1'); await countRows(); } catch (e) { print('初始化失败: $e'); loading = false; // 出错时强制停止加载 } }
修改countRows方法:
static Future countRows() async { if (_worksheet == null) { loading = false; return; } try { while ((await _worksheet!.values.value(column: 1, row: numberOfTransactions + 1)) != '') { numberOfTransactions++; } await loadTransactions(); } catch (e) { print('统计行数失败: $e'); loading = false; } }
修改loadTransactions方法:
static Future loadTransactions() async { if (_worksheet == null) { loading = false; return; } try { currentTransactions.clear(); // 修复循环条件,避免漏掉最后一行数据 for (int i = 1; i <= numberOfTransactions; i++) { final String dataNama = await _worksheet!.values.value(column: 1, row: i + 1); final String dataPaspor = await _worksheet!.values.value(column: 2, row: i + 1); final String dataSponsor = await _worksheet!.values.value(column: 3, row: i + 1); final String dataTanggal = await _worksheet!.values.value(column: 4, row: i + 1); currentTransactions.add([dataNama, dataPaspor, dataSponsor, dataTanggal]); } print(currentTransactions); } catch (e) { print('加载数据失败: $e'); } finally { loading = false; // 无论成功失败都停止加载 } }
4. 优化数据加载方式,减少网络请求
原代码循环调用单个单元格查询,网络请求次数过多易超时。改用批量获取整行数据:
static Future loadTransactions() async { if (_worksheet == null) { loading = false; return; } try { // 批量获取第2行开始的所有数据行(假设第1行是表头) final rows = await _worksheet!.values.allRows(fromRow: 2, length: numberOfTransactions); currentTransactions = rows.map((row) => row.take(4).toList()).toList(); print(currentTransactions); } catch (e) { print('加载数据失败: $e'); } finally { loading = false; } }
5. 真机网络环境测试
- 切换Wi-Fi和移动数据,测试不同网络环境下的连接情况。
- 确认真机网络可正常访问Google相关服务,部分地区需检查网络是否存在访问限制。
内容的提问来源于stack exchange,提问作者Theo Haganta
相关产品推荐
相关产品推荐

