【问题标题】:Android sometimes throw fatal error when creating NotificationAndroid 在创建通知时有时会抛出致命错误
【发布时间】:2020-06-11 14:26:33
【问题描述】:

我对 xamarin 非常陌生,并创建了下载通知。它的工作时间最长,但有时应用程序会在创建通知后出现胎儿错误并关闭。

我只得到这种融洽的关系,我不知道如何追踪。

=================================================================
    Native Crash Reporting
=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries 
used by your application.
=================================================================
06-02 05:39:28.296 E/mono-rt (16761): /proc/self/maps:
06-02 05:39:28.296 E/mono-rt (16761): 12c00000-16f40000 rw-p 00000000 00:01 25459                              /dev/ashmem/dalvik-main space (region space)_4473_4473 (deleted)
06-02 05:39:28.296 E/mono-rt (16761): 16f40000-172c0000 rw-p 04340000 00:01 25459                              /dev/ashmem/dalvik-main space (region space)_4473_4473 (deleted)
06-02 05:39:28.296 E/mono-rt (16761): 172c0000-17340000 ---p 046c0000 00:01 25459                              /dev/ashmem/dalvik-main space (region space)_4473_4473 (deleted)
06-02 05:39:28.296 E/mono-rt (16761): 17340000-173c0000 rw-p 04740000 00:01 25459                              /dev/ashmem/dalvik-main space (region space)_4473_4473 (deleted)
06-02 05:39:28.296 E/mono-rt (16761): 173c0000-18380000 ---p 047c0000 00:01 25459                              /dev/ashmem/dalvik-main space (region space)_4473_4473 (deleted)
06-02 05:39:28.296 E/mono-rt (16761): 18380000-183c0000 rw-p 05780000 00:01 25459                              /dev/ashmem/dalvik-main space (region space)_4473_4473 (deleted)
06-02 05:39:28.297 E/mono-rt (16761): 183c0000-18400000 ---p 057c0000 00:01 25459                              /dev/ashmem/dalvik-main space (region space)_4473_4473 (deleted)

=================================================================
    Basic Fault Adddress Reporting
=================================================================
Memory around native instruction pointer (0x6f51ecb678):0x6f51ecb668  00 1c 40 b9 c0 03 5f d6 fd 7b bf a9 fd 03 00 91  ..@..._..{......
0x6f51ecb678  08 20 40 b9 a8 00 c8 37 88 01 e0 37 00 00 40 f9  . @....7...7..@.
0x6f51ecb688  fd 7b c1 a8 c0 03 5f d6 60 08 00 b0 01 0a 00 f0  .{...._.`.......
0x6f51ecb698  03 0a 00 f0 00 24 06 91 21 80 08 91 63 8c 0a 91  .....$..!...c...

No native Android stacktrace (see debuggerd output).

这是我启动服务的方式

  Methods.OnVideoDownload += new Action<Manager.Models.Container.YoutubeFileDownloadItem>((video) =>
    {
        if (!ObjectCacher.DownloadingFiles.ContainsKey(video.VideoId))
        {
            ObjectCacher.DownloadingFiles.Add(video.VideoId, video);
            var intent = new Intent(this, typeof(FileService));
            intent.PutExtra(FileService.URL, new AppManager().GetVideoStreamUrl(video.VideoId, 18));
            intent.PutExtra(FileService.Title, video.Title);
            intent.PutExtra(FileService.DirectoryName, Path.Combine(Methods.LocalMusicFolder, video.Playlist));
            intent.PutExtra(FileService.FileName, video.GenerateLocalPath());

            if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
            {
                var servive = this.StartForegroundService(intent);
            }
            else
            {
                this.StartService(intent);
            }
        }
    });

这里是 onstartCommand,在返回 StartCommandResult.Sticky; 后应用程序关闭

 public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
    {
        PendingIntent pendingIntent = PendingIntent.GetActivity(MainActivity.Current, 0, intent, 0);
        var url = intent.GetStringExtra(URL);
        var fileName = intent.GetStringExtra(FileName);
        var directory = intent.GetStringExtra(DirectoryName);
        var title = intent.GetStringExtra(Title);

        intent.AddFlags(ActivityFlags.ClearTop);
        var nb = NotificationHelper.GetNotification1(GetString(Resource.String.Downloading) + " " + title, GetString(Resource.String.DownloadProgress), pendingIntent);


        if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
        {
            StartForeground(NotificationId, nb.Build());
        }


        var _downlodFile = new DownlodFile(url, directory, fileName, new Action<int>((procent) =>
        {
            nb.SetContentText("")
            .SetContentTitle(GetString(Resource.String.Downloading) + $" ({procent}%) " + title)
            .SetProgress(100, procent, false);
            NotificationHelper.Notify(NotificationId, nb);
        }), new Action(async () =>
        {
            try
            {
                await Methods.DownloadCompleted(fileName);
            }
            catch (Exception ex)
            {
            }
            nb.SetOnlyAlertOnce(false).SetProgress(0, 0, false)
            .SetContentText(GetString(Resource.String.Finished));
            await Task.Delay(100);
            NotificationHelper.Notify(NotificationId, nb);
            ObjectCacher.RandomIdCacher.Remove(NotificationId);
            nb.Dispose();
            NotificationHelper.Dispose();
            if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
            {
                StopForeground(true);
            }

        }), new Action<Exception>((e) =>
        {
            nb.SetProgress(0, 0, false).SetContentText("Error: Something went wrong.\n Please try agen later.");
            NotificationHelper.Notify(NotificationId, nb);
            ObjectCacher.RandomIdCacher.Remove(NotificationId);
            nb.Dispose();
            NotificationHelper.Dispose();
            if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
            {
                StopForeground(true);
            }
        }));
        _downlodFile.Download();
        NotificationHelper.Notify(NotificationId, nb);
        return StartCommandResult.Sticky;
    }
}

这里是 DownloadFile 对象

public class DownlodFile : IDisposable
{
    private readonly WebClient _client;
    private readonly Action<int> _onProgress;
    private readonly Action<Exception> _onError;
    private readonly Action _onComplete;
    private readonly Uri _url;
    private readonly string _fileName;
    private readonly string _directoryName;

    public bool Downloading { get; private set; }
    // this will be true when the complete event trigger or an error trigger
    public bool FileCompleted { get; private set; }

    /// <summary>
    /// DownlodFile
    /// </summary>
    /// <param name="url">File Url</param>
    /// <param name="filelocation">Where file will e saved on the system</param>
    /// <param name="progressChanged">Get the ProgressPercentage</param>
    /// <param name="error">When an error accord</param>
    public DownlodFile(string url, string directoryName, string fileName, Action<int> progressChanged = null, Action completed = null, Action<Exception> error = null)
    {
        _client = new WebClient();
        _onProgress = progressChanged;
        _fileName = fileName;
        _directoryName = directoryName;
        _onComplete = completed;
        _onError = error;
        _url = url.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ? new Uri(url) : new Uri("http://" + url);

        var proc = 0;
        _client.DownloadProgressChanged += new DownloadProgressChangedEventHandler((o, e) =>
        {
            if (proc != e.ProgressPercentage)
                _onProgress?.Invoke(e.ProgressPercentage);
            proc = e.ProgressPercentage;

        });
        _client.DownloadDataCompleted += new DownloadDataCompletedEventHandler((o, e) =>
        {
            try
            {
                File.WriteAllBytes(Path.Combine(_directoryName, _fileName), e.Result);
                _onComplete?.Invoke();
                this.Dispose();
            }
            catch
            {
                this.Dispose();
            }

        });



    }


    public void Download()
    {
        try
        {
            if (!Directory.Exists(_directoryName))
                Directory.CreateDirectory(_directoryName);

            if (!FileCompleted)
            {
                Downloading = true;
                // Start downloading the file
                _client.DownloadDataAsync(_url);
            }
            else throw new Exception("DownlodFile is already disposed, please Create a new one");
        }
        catch (Exception ex)
        {
            FileCompleted = true;
            this.Dispose();
            _onError?.Invoke(ex);

        }

    }


    public void Dispose()
    {
        if (!FileCompleted)
            _client.Dispose();
        FileCompleted = true;
        Downloading = false;
    }
}

}

任何导致此问题的原因或什至如何跟踪它的任何想法。

更新新的错误日志

Time    Device Name Type    PID Tag Message
06-02 14:40:50.354  Samsung SM-G960F    Error   22222   ActivityThread  android.app.IntentReceiverLeaked: Service com.google.android.youtube.api.service.YouTubeService has leaked IntentReceiver ahmr@b5a2701 that was originally registered here. Are you missing a call to unregisterReceiver()?
    at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:1538)
    at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:1277)
    at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1555)
    at android.app.ContextImpl.registerReceiver(ContextImpl.java:1528)
    at android.app.ContextImpl.registerReceiver(ContextImpl.java:1516)
    at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:636)
    at ajgx.<init>(SourceFile:42)
    at ajic.get(SourceFile:30)
    at baxz.get(SourceFile:9)
    at baxw.get(SourceFile:4)
    at mlt.F(SourceFile:23)
    at ahlo.a(SourceFile:5)
    at ahlo.get(SourceFile:7)
    at baxz.get(SourceFile:9)
    at mma.a(SourceFile:3)
    at mkr.<init>(SourceFile:11)
    at com.google.android.apps.youtube.embeddedplayer.service.service.jar.ApiPlayerService.<init>(SourceFile:46)
    at com.google.android.apps.youtube.embeddedplayer.service.service.jar.ApiPlayerFactoryService$1.run(SourceFile:4)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:6981)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)

【问题讨论】:

    标签: c# xamarin xamarin.forms xamarin.android


    【解决方案1】:

    可能有多种原因,具体取决于您运行的设备(手机/模拟器、Android 版本、授予用户权限之前/之后的错误、权限被拒绝)。

    我怀疑的原因是您没有正确处理权限,另一个可能的原因可能是您没有在 UI 线程中运行文件下载工作。所以将行更新为这样的内容

    this.Activity.RunOnUiThread(() =>
    {
        _downlodFile.Download();
    });
    

    你可以

    1. 创建系统捕获点异常,
    2. 启动分析器以跟踪错误,
    3. (并且应该)使用 try-catch 语句, 基本上弄清楚代码在哪一行崩溃,以及内部堆栈跟踪是什么。

    【讨论】:

    • 我明白你的意思。我确实添加了 try catch,但它从未触发 catch 事件。该应用程序仅关闭。这只是有时并不总是发生。这种情况发生在移动设备和模拟器上。我不认为它的许可问题,因为它有效,只是有时会发生。并且下载在一个单独的线程上运行,因为它使用 webclient downloadasyn 和 progress changed 方法。现在分析器你是什么意思,你能详细说明一下吗
    • 你能用下载异步更新代码吗,因为我只看到 _downlodFile.Download();而且它似乎不是异步的。它有时可能会工作,因为它实际上在 UI 线程上运行的那几次,而它崩溃的时候,它却没有。同样对于分析,您应该使用谷歌搜索“使用 Xamarin Profiler 诊断 Android 崩溃”
    • 会这样做,我更新代码,现在你可以看到DownloadFile的内容
    • 我没有 xamarin 分析器,无法在 vs 2017 上安装它,但启动了 android 日志并获得了新信息,请查看 upp。也会尝试解决这个问题
    • 您的问题似乎可以使用stackoverflow.com/questions/9078390/… 之类的方法解决。根据您的 API 版本,它可能会以不同的方式修复。尝试使用低于 API 26 的设备和等于或高于 Anroid API 26 (Android O) 的设备测试相同的东西forums.xamarin.com/discussion/146397/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-02
    • 1970-01-01
    相关资源
    最近更新 更多