-2

I am working on an app that plays music. Now, I have a function in my main class that chooses a random new song and plays said song:

    private void ChooseRandomNewSongAndPlay(bool songHasCompleted)
    {
        Random rnd = new Random();
        int rndValue = rnd.Next(0, Mp3ObjectSmall.Count());
        int currentPos = 0;

        if (!songHasCompleted)
        {
            currentPos = mediaPlayer.CurrentPosition; // if song infact has completed, reset position to else save current position (when next has been pressed)
        }

        WriteSeekingToDataBase(currentPos, CurrentSongObject);
        mediaPlayer.Stop();

        if (Android.Net.Uri.Parse(CurrentSongObject.Mp3Uri) != null)
        {
            PhotoAlbumAdapter.OldSongUri = Android.Net.Uri.Parse(CurrentSongObject.Mp3Uri);
        }

        PhotoAlbumAdapter.NewSongUri = (Android.Net.Uri.Parse(Mp3ObjectSmall[rndValue].Mp3Uri));

        PlayMusic((Android.Net.Uri.Parse(Mp3ObjectSmall[rndValue].Mp3Uri)));
    }

But I also set up a broadcast receiver, so when the user is in his car and clicks on next song from the car stereo, I also want the above function to be played. But here is the problem:

I cannot make this above function public static since it calls other non static functions. I would have to make those static too, but that would cause many, many other errors and is not a good solution at all I believe.

Also, I cannot create a new object of my main class in within the broadcast receiver as such: class xy = new class(). I cannot do that, because that would also create another object of my mediaplayer object, but this object needs to be the same to skip to a next some. If it isnt, just anoither song is played on top of the first song which of course is also not good.

Lastly, I cannot just hand over the class as a parameter to the constructor of the broadcast receiver. I am getting told then that the braodcast receiver needs to have a "standart constructor" so I cannot alter the parameters.

Unfortunately, these 3 optiones are all I believe I have and neither seems to work. What I really, really do not want to do is to copy paste all functions from my main class into the broadcast receiver for obvious reasons.

Can you guys help me out here? Thank you!

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
innomotion media
  • 862
  • 11
  • 30
  • Possible duplicate of [What is a singleton in C#?](https://stackoverflow.com/questions/2155688/what-is-a-singleton-in-c) – mjwills Nov 07 '18 at 09:53
  • If a singleton or static class would require too much refactoring, consider passing a function pointer via an Action or Func instance. – Ryan Pierce Williams Nov 07 '18 at 10:02
  • I believe I cannot make my "mainActivity" as it is called in android, become a singleton but you are right, it would be too much refactoring. Can you elaborate the idea of the function pointer? thank you! – innomotion media Nov 07 '18 at 10:04
  • Maybe you can make your mediaplayer object `static` and take care that is created only once, this way you can create many instances of your main class. – Alessandro D'Andria Nov 07 '18 at 10:11
  • @innomotionmedia say you had a function like: **object myFunc(object p)** in your class then you can create a function pointer like so: **Func fp = this.myFunc;** (I usually do this in VB.NET at work, so syntax might be slightly off). The last template parameter is the return type, and the other type parameters need to match the input types for the function. – Ryan Pierce Williams Nov 07 '18 at 10:24

3 Answers3

0

You didn't specified if you broadcast receiver is an activity-local broadcast receiver or application-wide broadcast receiver.

LocalBroadcastReceivers can be created as activity's property and let you broadcast messages within the app, while classic BroadcastReceivers can let you respond to an action coming from outside your app even if your app is closed.

If you have a BroadcastReceiver you can, when it receives a message from, make it republish the message through LocalBroacastManager. Also your activity must setup a LocalBroadcastReceiver that handles that particular internal broadcast message.

Doing so, you don't worry about Activity state. When the global BroadcastReceiver is invoked, it broadcast the message inside the application, and if there's some receiver listening to they will be invoked all, otherwise the message is simply ignored with no bugs, retain cycles or crashes.

I suppose you are using Xamarin Android. You can get the full documentation about receivers here https://learn.microsoft.com/en-us/xamarin/android/app-fundamentals/broadcast-receivers

Luca Corradi
  • 2,031
  • 1
  • 16
  • 17
0

The easiest way is to just create a single static instance from your class and fire the functions:

    public static Activity_Player Instance;

then in the broadcast recevier:

Instance.MYFUNCTION

innomotion media
  • 862
  • 11
  • 30
-1

How about creating a property on the broadcast receiver and using that to pass a reference to the main class?

public class MyBroadcastReceiver
{
    // Constructor
    public MyBroadcastReceiver() {}

    // property 
    public MyMainClass {get;set;}
}

public MyMainClass 
{
    private void CreateBroadcastReceiver()
    {
        var br = new MyBroadcastReceiver();
        br.MyMainClass = this;
    } 
}
Robin Bennett
  • 3,192
  • 1
  • 8
  • 18
  • In android scenario is a really bad design to keep a reference to activity in the broadcast receiver. Creates a retain cycle and Activity could be not invokable at all in that moment. – Luca Corradi Nov 07 '18 at 10:19
  • Hello and thank you. Its an interessting idea, however, even if I am setting the property to my class once the broadcast receiver starts its magic the object is null and the app crashes... – innomotion media Nov 07 '18 at 10:19