How to play music from url in Xamarin.Forms? - c#

I am gonna build Xamarin.Forms app which play music from url.
I used dependency service for each platform implementation.
[assembly: Dependency(typeof(AudioSerivce))]
namespace xxx.Droid
{
public class AudioSerivce : IAudio
{
int clicks = 0;
MediaPlayer player;
public AudioSerivce()
{
}
public bool Play_Pause (string url)
{
if (clicks == 0) {
this.player = new MediaPlayer();
this.player.SetDataSource(url);
this.player.SetAudioStreamType(Stream.Music);
this.player.PrepareAsync();
this.player.Prepared += (sender, args) =>
{
this.player.Start();
};
clicks++;
} else if (clicks % 2 != 0) {
this.player.Pause();
clicks++;
} else {
this.player.Start();
clicks++;
}
return true;
}
public bool Stop (bool val)
{
this.player.Stop();
clicks = 0;
return true;
}
}
}
and calling it
DependencyService.Get<IAudio>().Play_Pause("https://www.searchgurbani.com/audio/sggs/1.mp3");
If I check log, it seems everything is ok.
But I can't hear sound on android phone.
If anyone has some suggestion, please let me know.
Thanks

From:
https://forums.xamarin.com/discussion/64218/no-video-player-really
I suspect that there may be a problem related to an incompatibility between Octane Video player and Android Emulator, are you using a emulator/simulator?
Also another suggestion is to add this permissions:
INTERNET
WRITE_EXTERNAL_STORAGE
READ_EXTERNAL_STORAGE
To your Android app.
If that does not work try to use another url and compare if it working with other url's.

Related

Ads are working In Editor but not In Android

I am trying to use ads In my game . They are properly working in Unity but not in Android. Because of I am using unity 2018.4.25f1 personal so it's supporting older version of unity monetization asset. Maybe it's a problem but here is my code of Rewarded Video CSharp file
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Advertisements;
[RequireComponent(typeof(Button))]
public class RewardedVideo : MonoBehaviour, IUnityAdsListener
{
#if UNITY_IOS
private string gameId = "3853032";
#elif UNITY_ANDROID
private string gameId = "3853033";
#endif
[SerializeField]Button myButton;
[SerializeField]GameObject errorMessage;
public string myPlacementId = "rewardedVideo";
void Start()
{
// Map the ShowRewardedVideo function to the button’s click listener:
if (myButton)
myButton.onClick.AddListener(ShowRewardedVideo);
// Initialize the Ads listener and service:
Advertisement.AddListener(this);
Advertisement.Initialize(gameId, true);
}
public void okError()
{
errorMessage.SetActive(false);
}
// Implement a function for showing a rewarded video ad:
public void ShowRewardedVideo()
{
if(Advertisement.IsReady() == true)
Advertisement.Show(myPlacementId);
else
errorMessage.SetActive(true);
}
// Implement IUnityAdsListener interface methods:
public void OnUnityAdsReady(string placementId)
{
// If the ready Placement is rewarded, activate the button:
if (placementId == myPlacementId)
{
// myButton.interactable = true;
}
}
public void OnUnityAdsDidFinish(string placementId, ShowResult showResult)
{
// Define conditional logic for each ad completion status:
if (showResult == ShowResult.Finished)
{
int levels = PlayerPrefs.GetInt("unlockedLevel", 1);
if(levels != 5)
{
PlayerPrefs.SetInt("unlockedLevel", levels+1);
}
}
else if (showResult == ShowResult.Skipped)
{
// Do not reward the user for skipping the ad.
}
else if (showResult == ShowResult.Failed)
{
Debug.LogError("The ad did not finish due to an error");
}
}
public void OnUnityAdsDidError(string message)
{
// Log the error.
}
public void OnUnityAdsDidStart(string placementId)
{
// Optional actions to take when the end-users triggers an ad.
}
}
Downloaded asset from Assets store not from package manager. I saw Unity help, unity forum, stackoverflow but nothing solved my problem
Have you any suggestion?

Android 8 receive of stop receiving media buttons events

I have a service that listens to media buttons, but I only want to listen to those when my service is running since I have a button on the UI to start/stop the service.
How can I achieve the following two actions:
On MyService start-up, start receiving media button events to com.myApp/MyService.
On MyService end, stop receiving media button events in com.myApp/MyService.
The related logs are the following:
D MediaSessionService: Sending KeyEvent { action=ACTION_DOWN, keyCode=KEYCODE_HEADSETHOOK, scanCode=226, metaState=0, flags=0x8, repeatCount=0, eventTime=13258317, downTime=13258317, deviceId=4, source=0x101 } to com.myApp/MyService (userId=0)
Note:
I found out that I can start receiving media events after my app started to play audio. This is however not ideal, since I don't want to play audio in my app. (I am only using media events in order to trigger voice recognition)
After I played audio, my service is apparently the default media receiver. This means that when a media button is pressed, my service get instantiated, does nothing, and get destroyed. This is not an idea behavior for the end user since my app ends up 'stealing' these events that could potentially be handled by something else.
Overriding OnStartCommand() in my service does not help
Calling SetMediaButtonReceiver on the MediaSession does not help either
Using a BroadcastReceiver with the intent "android.intent.action.MEDIA_BUTTON" registered in the AudioManager does not work either
Relevant code (in C#, I am on Xamarin.Forms, but that should not have any impact on the way to achieve this)
public class MediaSessionCompatCallback : MediaSessionCompat.Callback
{
public Func<Intent, bool> MediaButtonEvent { get; set; }
public override bool OnMediaButtonEvent(Intent mediaButtonEvent) => MediaButtonEvent?.Invoke(mediaButtonEvent) ?? false;
}
[Service(Exported = true, Enabled = true)]
[IntentFilter(new[] { ServiceInterface })]
public class MediaBrowserService : MediaBrowserServiceCompat, AudioManager.IOnAudioFocusChangeListener
{
private MediaSessionCompat mediaSession;
private MediaSessionCompatCallback mediaSessionCallback;
private void CreateMediaSessionCallback()
{
mediaSessionCallback = new MediaSessionCompatCallback()
{
MediaButtonEvent = OnMediaButtonEvent
};
}
private void SetupMediaSession()
{
CreateMediaSessionCallback();
var stateBuilder = new PlaybackStateCompat.Builder().SetActions(PlaybackStateCompat.ActionPlay | PlaybackStateCompat.ActionPlayPause);
mediaSession = new MediaSessionCompat(this, nameof(MediaBrowserService));
mediaSession.SetFlags(MediaSessionCompat.FlagHandlesMediaButtons | MediaSessionCompat.FlagHandlesTransportControls);
mediaSession.SetPlaybackState(stateBuilder.Build());
mediaSession.SetCallback(mediaSessionCallback);
mediaSession.Active = true;
SessionToken = mediaSession.SessionToken;
}
private void BuildNotification() { [...] }
public override void OnCreate()
{
base.OnCreate();
SetupMediaSession();
StartForeground(135, BuildNotification());
ContextCompat.StartForegroundService(ApplicationContext, new Intent(ApplicationContext, Java.Lang.Class.FromType(typeof(MediaBrowserService))));
}
public override void OnDestroy()
{
base.OnDestroy();
if (mediaSession != null)
{
mediaSession.Active = false;
mediaSession.SetCallback(null);
mediaSession.Release();
mediaSession.Dispose();
mediaSession = null;
}
if (mediaSessionCallback != null)
{
mediaSessionCallback.Dispose();
mediaSessionCallback = null;
}
StopForeground(true);
StopSelf();
}
}

Xamarin Audio players not working in Galaxy S8

I am trying to get a shoutcast URL (.stream) to stream audio in a cross-platform application. I've started with the Android app first and I cannot get the audio playing on the test device Samsung Galaxy S8.
However, the audio players work fine within the Emulator. If it weren't for the test device I would've assumed everything was working.
I've tried using "the local MediaPlayer" and "Plugin.MediaManager": Both work in the Emulator but none on the device. I have enabled the permissions required in the manifest: ACCESS_NETWORK_STATE, INTERNET, MEDIA_CONTENT_CONTROLS, RECORD_AUDIO, WAKE_LOCK, READ_EXTERNAL_STORAGE
(using MediaManager plugin)
in MainActivy:
protected override void OnCreate(Bundle savedInstanceState)
{
.....
CrossMediaManager.Current.Init(this);
.....
}
public class StreamingService: IStreaming.IStreaming
{
bool IsPrepared = false;
public async void Play()
{
await CrossMediaManager.Current.Play("http://someUrl/stream");
}
public void Pause()
{
CrossMediaManager.Current.Pause();
}
public void Stop()
{
CrossMediaManager.Current.Stop();
IsPrepared = false;
}
public int getResponse()
{
if (CrossMediaManager.Current.IsPlaying())
return 1;
else
return 0;
}
}
If I look at the data usage for the app on the device it is set to 0kb after a few tries it goes up by the kb currently at 3.24kb data usage. It doesnt appear that the media player is trying to access the stream, or can even access the stream.
I found a nuget package: LibVLCSharp.Forms
in the Main application created a class:
using LibVLCSharp.Shared;
public class RadioStream
{
readonly LibVLC _libVLC;
readonly MediaPlayer _mp;
public RadioStream()
{
if (DesignMode.IsDesignModeEnabled) return;
Core.Initialize();
_libVLC = new LibVLC();
_mp = new MediaPlayer(_libVLC);
}
public void Init()
{
_mp.Media = new Media(_libVLC, "http://url/stream", FromType.FromLocation);
_mp.Media.AddOption(":no-video");
}
public void Play(bool play)
{
if (play)
_mp.Play();
else _mp.Pause();
}
public bool isPlaying()
{
if (_mp.IsPlaying == false)
return false;
else
return true;
}
}
And its working!
In a while loop I check the isPlaying() that allows me to set the status of the stream and display accordingly.
Its simple at the moment, and stops playing when the internet state changes. But the above is working for simple playback.

user can't log into google play services

User authentication doesn't work in my app that I'm making for android. This is the script that is attached to an empty game object in my main menu.
void Start()
{
PlayGamesPlatform.Activate();
PlayGamesPlatform.DebugLogEnabled = true;
}
public void LoadScene(string sceneName)
{
SceneManager.LoadScene(sceneName);
}
public void showleaderboard()
{
if(Social.localUser.authenticated)
{
PlayGamesPlatform.Instance.ShowLeaderboardUI("CgkIq82p4qcNEAIQAQ");
}
else
{
Debug.Log("leaderboard not working");
}
}
public void userlogin()
{
Social.localUser.Authenticate((bool success) =>
{
if(success)
{
Debug.Log("Logged in");
}
else
{
Debug.Log("Login failed");
}
});
}
The functions are attached to buttons and I always get the log "Login Failed" in my console. I tested this on an android device that was able to log into google play services in other published apps.
You should add your account as test account in Google play services panel, otherwise it will be always a failed login.

Call Java function from Unity3D

I have an android application developed by Unity3D written by C# and I wan to hide the bottom bar when running my app. So I searched around and found that I need to use setSystemUiVisibility function from Java. Here is the code I found:
using UnityEngine;
public class DisableSystemUI
{
static AndroidJavaObject activityInstance;
static AndroidJavaObject windowInstance;
static AndroidJavaObject viewInstance;
public delegate void RunPtr();
public static void Run()
{
if (viewInstance != null) {
viewInstance.Call("setSystemUiVisibility", 2);
}
}
static DisableSystemUI()
{
if (Application.platform != RuntimePlatform.Android)
return;
DisableNavUI();
}
static void DisableNavUI()
{
if (Application.platform != RuntimePlatform.Android)
return;
using (AndroidJavaClass unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
activityInstance = unityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity");
windowInstance = activityInstance.Call<AndroidJavaObject>("getWindow");
viewInstance = windowInstance.Call<AndroidJavaObject>("getDecorView");
AndroidJavaRunnable RunThis;
RunThis = new AndroidJavaRunnable(new RunPtr(Run));
activityInstance.Call("runOnUiThread", RunThis);
}
}
}
I tried to call DisableSystemUI.Run(); in my main scene. I rooted my device but the app quits after I run it. Not sure what's wrong with it? Thanks for help.
it would be better to understand if you post the java code
i too had a same problem
try this
viewInstance.Call("setSystemUiVisibility", "SYSTEM_UI_FLAG_FULLSCREEN");
or this
viewInstance.Call("setSystemUiVisibility", "SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN");
should work....

Categories