Xamarin Android写入JSON文件遇权限与空引用异常求助
Hey there, let's work through your JSON storage problems step by step—they're common when switching to Xamarin from plain C#, so don't stress!
First, Let's Clarify Folder Permissions
- Assets Folder: This is supposed to be read-only! It's packaged directly with your app, so you can't write to it at runtime. Use it only for static, unchanging data (like default configurations you might want to copy to a writable location later).
- SpecialFolder.Personal: This is actually the right choice for writable app-specific data—each app gets its own private directory here that only it can access. The issues you're seeing come from how your code handles new files, not the path itself.
- Other System Paths: Most system folders (like Downloads or Documents) require extra permissions (especially on Android 10+ with scoped storage), so stick to
SpecialFolder.Personalunless you explicitly need to share files with other apps.
Why GetAllPlayerData() Returns Null
Your ReadFile method creates an empty file when it doesn't exist, but then tries to deserialize an empty string. Newtonsoft.Json returns null when deserializing an empty string to a List<Player>, which is why your method returns null. Let's fix that:
Modified Code with Fixes
1. Fix the ReadFile Method
Add checks for empty content and handle deserialization failures gracefully:
/// <summary> /// Method to read JSON data from a specified file path. /// </summary> /// <param name="path"></param> /// <returns></returns> private List<Player> ReadFile(string path) { // If file doesn't exist, create it and return an empty list if (!File.Exists(path)) { using (File.Create(path)) { } // Using statement auto-disposes the stream return new List<Player>(); } string jsondata = File.ReadAllText(path); // Handle empty file content if (string.IsNullOrWhiteSpace(jsondata)) { return new List<Player>(); } // Add error handling for malformed JSON try { return JsonConvert.DeserializeObject<List<Player>>(jsondata); } catch (JsonException ex) { // Log the error (use a library like Xamarin.Essentials or Serilog for better logging) Console.WriteLine($"Deserialization failed: {ex.Message}"); return new List<Player>(); } }
2. Ensure Path Initialization is Timely
If you're getting a null reference on the path, it might be because you're initializing it too early (before the app has access to system folders). Move path initialization to your class constructor instead of field initialization:
private string playerdata; private string teamdata; // Replace with your actual class name public PlayerDataManager() { var personalFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal); playerdata = Path.Combine(personalFolder, "playerdata.json"); teamdata = Path.Combine(personalFolder, "team.json"); }
3. Copy Initial Data from Assets (If Needed)
If you have a default playerdata.json in Assets that you want to use as a starting point, add a method to copy it to the writable directory on first launch:
// For Xamarin.Android, use Assets; for Xamarin.iOS, use NSBundle // If using Xamarin.Forms, use DependencyService to access platform-specific assets private void CopyInitialPlayerData() { if (File.Exists(playerdata)) return; // Example for Xamarin.Android: using (var assetStream = Assets.Open("playerdata.json")) using (var fileStream = new FileStream(playerdata, FileMode.Create)) { assetStream.CopyTo(fileStream); } }
Call this method when your app starts (like in OnCreate for Android, FinishedLaunching for iOS, or your Forms app's App constructor).
Verify the Write Method
Your WriteFile method looks solid, but add a quick check to avoid writing null data:
private void WriteFile(string path, List<Player> data) { if (data == null) { data = new List<Player>(); } string json = JsonConvert.SerializeObject(data, Formatting.Indented); File.WriteAllText(path, json); }
With these changes, your app should correctly read/write JSON data to the private app directory without null references or permission errors.
内容的提问来源于stack exchange,提问作者JamesTheHunt

