Xamarin Android中NLog写入外部存储无日志文件生成求助
我之前在Xamarin.Android上用NLog写外部存储日志时也踩过一模一样的坑——控制台输出正常,但文件死活不生成,结合Android的权限机制和NLog的配置细节,给你梳理几个最可能的排查方向:
权限问题(最常见):
虽然你说清单文件加了配置,但Android 6.0(API 23)及以上需要动态申请存储权限,清单里的静态权限只是声明,实际运行时必须主动请求。另外,Android 10(API 29)开启了分区存储,即使有WRITE_EXTERNAL_STORAGE权限,也不能随意访问公共目录;Android 11+如果要写公共目录,还需要申请MANAGE_EXTERNAL_STORAGE权限(这个权限需要用户手动在设置里开启)。
优先推荐把日志写到应用专属外部存储目录,这个目录不需要动态权限,路径可以用Context.GetExternalFilesDir(Environment.DirectoryLogs),NLog里可以用${android:externalFilesDir}/logs/app.log来引用。路径配置错误:
别硬写/sdcard/xxx这类路径,不同设备的外部存储路径可能不一样。NLog提供了Android专属的变量,比如:${android:externalStorageDirectory}:对应系统外部存储根目录${android:externalFilesDir}:对应应用专属外部存储目录
同时要确保NLog文件目标的createDirs="true",这样会自动创建不存在的日志目录。
NLog配置细节遗漏:
- 检查NLog.config的复制属性:在Visual Studio里右键NLog.config → 属性 → 复制到输出目录,设为「始终复制」,否则配置文件不会被打包到应用Assets目录,NLog加载不到配置。
- 检查日志级别过滤:比如文件目标的
minlevel设为Error,但你只打了Info级别的日志,自然不会写入;或者rules里没把日志路由到文件目标。 - 开启NLog内部日志排查:在NLog.config里添加内部日志配置,能看到NLog初始化和写入时的错误信息:
<nlog internalLogLevel="Debug" internalLogFile="${android:externalFilesDir}/nlog-internal.log">
动态权限申请示例代码:
如果一定要写公共目录,需要在MainActivity里主动申请权限:protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); // 检查并申请存储权限 if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) != Permission.Granted) { ActivityCompat.RequestPermissions(this, new string[] { Manifest.Permission.WriteExternalStorage, Manifest.Permission.ReadExternalStorage }, 1001); } else { InitNLogAndTest(); } } public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults) { base.OnRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 1001 && grantResults.Any(p => p == Permission.Granted)) { InitNLogAndTest(); } else { Toast.MakeText(this, "存储权限被拒绝,无法写入外部日志文件", ToastLength.Long).Show(); } } private void InitNLogAndTest() { LogManager.LoadConfiguration("NLog.config"); var logger = LogManager.GetCurrentClassLogger(); logger.Info("测试外部存储日志写入"); }推荐的NLog.config文件目标配置:
用应用专属外部存储,无需动态权限,省心:<targets> <target name="console" xsi:type="Console" /> <target name="file" xsi:type="File" fileName="${android:externalFilesDir}/logs/app.log" createDirs="true" layout="${longdate} ${level} ${message} ${exception:format=ToString}" /> </targets> <rules> <logger name="*" minlevel="Debug" writeTo="console" /> <logger name="*" minlevel="Info" writeTo="file" /> </rules>
先试试开启内部日志,看有没有具体的错误提示,比如权限不足、路径不存在,这能快速定位问题。
内容的提问来源于stack exchange,提问作者D3181

