在后台服务上调用方法会导致Null引用 - 我应该异步启动后台服务吗?

时间:2017-08-11 10:36:25

标签: c# android asynchronous xamarin xamarin.android

我正在尝试构建一个使用后台服务播放音频的媒体播放器。当用户单击开始按钮时,我启动后台音频服务,同时尝试在该后台服务上调用方法。

尝试在服务上调用方法时,我收到空引用错误,可能是因为服务尚未启动。

我应该异步启动后台服务并使用回调,还是我得到空引用的其他原因。如果我应该回电话,我该怎么做?

注意:从OnCreate方法启动后台服务时,我没有收到错误,应用程序按预期运行。

AudioActivity.cs

using System;
using Android.App;
using Android.Widget;
using Android.OS;
using Android.Content;

namespace AudioTour
{
    [Activity(Label = "AudioTour", MainLauncher = true, Icon = "@drawable/icon")]
    public class AudioActivity : Activity
    {     
        private AudioServiceConnection audioServiceConnection;
        public Binder binder;
        public bool isBound;

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            // Set Screen
            SetContentView(Resource.Layout.Main);
            // Find Buttons
            Button startButton = FindViewById<Button>(Resource.Id.startAudio);
            Button stopButton = FindViewById<Button>(Resource.Id.stopAudio);             
            // Assign Delegate Methods to Buttons
            startButton.Click += StartAudio;
            stopButton.Click += StopAudio;

            //StartAudioService();
            // If I start the audio service here I do not get the error
        }
        // Start Playing Audio
        void StartAudio(object sender, EventArgs ea)
        {
            // Create my background audio service
            // I have a strong hunch that start the audio service here means that when I come to the next line down it has not had time to prepare
            // Should I be starting this asynchronously with a call back?
            StartAudioService();
            // Call a method on my background service using a binder to start playing audio
            audioServiceConnection.Binder.service.StartAudio(); // ERROR HERE  // System.NullReferenceException: Object reference not set to an instance of an object.       

        }
        // Create the audio background service
        public void StartAudioService()
        {
            var audioServiceIntent = new Intent(this, typeof(AudioService));
            audioServiceConnection = new AudioServiceConnection(this);
            BindService(audioServiceIntent, audioServiceConnection, Bind.AutoCreate);
            StartService(new Intent(this, typeof(AudioService)));
        }
        // Stop Playing Audio
        void StopAudio(object sender, EventArgs ea)
        {
            audioServiceConnection.Binder.service.StopAudio();
            Console.WriteLine("Stopping Audio");         
        }
        protected override void OnDestroy()
        {
            base.OnDestroy();
        }
    }
}

AudioServiceConnection.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;

namespace AudioTour
{
    class AudioServiceConnection : Java.Lang.Object, IServiceConnection
    {
        AudioActivity activity;
        public bool IsConnected { get; private set; }
        public AudioServiceBinder Binder { get; private set; }

        public AudioServiceConnection(AudioActivity activity)
        {
            IsConnected = false;
            Binder = null;
            this.activity = activity;
        }

        public void OnServiceConnected(ComponentName name, IBinder service)
        {
            Binder = service as AudioServiceBinder;
            IsConnected = this.Binder != null;

           if (IsConnected)
            {
                Console.WriteLine("CONNECTED");
            }
            else
            {
                Console.WriteLine("DISCONNECTED");
            }
        }

        public void OnServiceDisconnected(ComponentName name)
        {
            activity.isBound = false;
        }
    }
}

* AudioServiceBinder *

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;

namespace AudioTour
{
    class AudioServiceBinder : Binder
    {
        public AudioService service { get; private set; }

        public AudioServiceBinder(AudioService _service)
        {
            this.service = _service;

        }      
    }
}

1 个答案:

答案 0 :(得分:0)

  

System.NullReferenceException:未将对象引用设置为对象的实例。

首先,我读了您之前的question,但我看不到您的AudioService OnBind方法,请确保返回{{1}在这个方法中,用法如下:

Binder

第二次,您应该在准备好之后调用[Service(Exported = false, Name = "com.AudioTour.AudioService")] public class AudioService : Service { private AudioServiceBinder mBinder; public override IBinder OnBind(Intent intent) { mBinder = new AudioServiceBinder(this); return mBinder; } public void StartAudio() { System.Diagnostics.Debug.WriteLine("StartAudio in AudioService"); } public void StopAudio() { System.Diagnostics.Debug.WriteLine("StopAudio in AudioService"); } } &#39; AudioService方法,给予延迟然后使用StartAudio方法将解决这个问题。用法如下:

StartAudio