2017-08-11 46 views
0

我正在嘗試構建使用後臺服務播放音頻的媒體播放器。當用戶點擊開始按鈕時,我開始後臺音頻服務,同時嘗試調用該後臺服務的方法。後臺服務調用方法導致空引用 - 我應該異步啓動後臺服務嗎?

嘗試調用服務上的方法時,我收到空引用錯誤,可能是因爲該服務尚未啓動。

我應該異步啓動後臺服務並使用回調,或者是我得到空引用的其他原因。如果我打電話回來,我該怎麼做?

注意:從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; 

     }  
    } 
} 
+0

() – Jim

+0

因爲你不'BindService'然後您應該查看示例代碼'StartService',BindService通常外面的服務等做..:HTTPS: //github.com/xamarin/monodroid-samples/tree/master/ApplicationFundamentals/ServiceSamples – SushiHangover

+0

請發佈您的'AudioServiceConnection'代碼。 –

回答

0

System.NullReferenceException:未將對象引用設置爲對象的實例。

首先,我看了你以前question,但我不能看到你的AudioServiceOnBind方法,確保在這個方法的返回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"); 
    } 
} 

,你應該在準備好之後撥打AudioService的方法StartAudio,給個延遲然後用StartAudio方法就可以解決這個問題。這樣的用法:

void StartAudio(object sender, EventArgs ea) 
{ 
     StartAudioService(); 

     Handler h = new Handler(); 
     Action myAction =() => 
     { 
      audioServiceConnection.Binder.service.StartAudio(); 
     }; 
     h.PostDelayed(myAction, 200); 
} 

public void StartAudioService() 
{ 
    var audioServiceIntent = new Intent(this, typeof(AudioService)); 
    audioServiceConnection = new AudioServiceConnection(this); 
    BindService(audioServiceIntent, audioServiceConnection, Bind.AutoCreate); 

    // when you use BindService method, it will start service automatically, there is no need to use StartService method again. 
    //StartService(new Intent(this, typeof(AudioService)));  
} 
在StartAudioService
+0

@Jim,你解決了你的問題嗎? –

+0

嗨@York Shen,我正試圖實現這一點,將更新 – Jim