I want to develop a music app for Windows 10 and I'm curious about the interface provided by Groove Music next to the volume bar. I've tried Googling to get more information about it but I haven't had any success whatsoever. When I'm playing music in Groove Music and I raise or lower the volume, the name as well as the artist and album artwork of the current song show up with music controls next to the volume indicator this:
I was wondering how I could create this dialog in my own app and what windows API's I'd have to look into.
I'm going to add my input to this even though there is a great answer already by #Stamos, because I've found that it is actually possible to use SystemMediaTransportControls from a native windows app (not only a universal app).
First thing, it does still require a reference to the universal winmd files, so it will only work on Win10. They will be located in the 10 sdk, and you can add them via the regular Add Reference -> Browse but you may need to change the filter on the bottom right of the dialog to "All Files" for them to show up. They are found here on my PC:
Windows.Foundation.UniversalApiContract: C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.UniversalApiContract\1.0.0.0\Windows.Foundation.UniversalApiContract.winmd
Windows.Foundation.FoundationContract: C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.FoundationContract\2.0.0.0\Windows.Foundation.FoundationContract.winmd
After you have the necessary references, you'll run into another problem - you can't access the transport controls via the usual SystemMediaTransportControls.GetForCurrentView(); (it will throw an exception) because you don't actually have a universal view. This is alleviated by using the following:
SystemMediaTransportControls systemControls =
BackgroundMediaPlayer.Current.SystemMediaTransportControls;
After this, feel free to use any of the samples online or Stamos' answer.
You need to use SystemMediaTransportControls
Here is a basic setup with Play and Pause. If you like to enable more controls you can do using the available properties for ex.
systemControls.IsNextEnabled = true;
and you have to add the case in the button switch.
case SystemMediaTransportControlsButton.Next:
//handle next song
break;
xaml
<MediaElement x:Name="mediaElement" Height="100" Width="100" AreTransportControlsEnabled="True"/>
C#
public MainPage()
{
this.InitializeComponent();
systemControls = SystemMediaTransportControls.GetForCurrentView();
// Register to handle the following system transpot control buttons.
systemControls.ButtonPressed += SystemControls_ButtonPressed;
mediaElement.CurrentStateChanged += MediaElement_CurrentStateChanged;
systemControls.IsPlayEnabled = true;
systemControls.IsPauseEnabled = true;
}
private void MediaElement_CurrentStateChanged(object sender, RoutedEventArgs e)
{
switch (mediaElement.CurrentState)
{
case MediaElementState.Playing:
systemControls.PlaybackStatus = MediaPlaybackStatus.Playing;
break;
case MediaElementState.Paused:
systemControls.PlaybackStatus = MediaPlaybackStatus.Paused;
break;
case MediaElementState.Stopped:
systemControls.PlaybackStatus = MediaPlaybackStatus.Stopped;
break;
case MediaElementState.Closed:
systemControls.PlaybackStatus = MediaPlaybackStatus.Closed;
break;
default:
break;
}
}
void SystemControls_ButtonPressed(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
{
switch (args.Button)
{
case SystemMediaTransportControlsButton.Play:
PlayMedia();
break;
case SystemMediaTransportControlsButton.Pause:
PauseMedia();
break;
case SystemMediaTransportControlsButton.Stop:
StopMedia();
break;
default:
break;
}
}
private async void StopMedia()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
mediaElement.Stop();
});
}
async void PlayMedia()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
if (mediaElement.CurrentState == MediaElementState.Playing)
mediaElement.Pause();
else
mediaElement.Play();
});
}
async void PauseMedia()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
mediaElement.Pause();
});
}
Output
Also if you want all this to work in background you will have to do a Declaration in Package.appxmanifest for a Background Tasks, enable audio and add an entry point like TestUWP.MainPage
<MediaElement x:Name="Media"
AreTransportControlsEnabled="True">
<MediaElement.TransportControls>
<MediaTransportControls
Style="{StaticResource MediaTCStyle}"/>
</MediaElement.TransportControls>
</MediaElement>
The style is quite big so i'm attaching a link
MediaTransportControls styles and templates
I got the style from the article(link above) and modified it in my own ResourceDictionary.
Related
I'm making a game. it has a login panel and rememmer me button. i keep the info on regedit. when I click rememmer me button it works and when I start game after click button it gets my info like id and pass but when I start again it deletes my id and pass on regedit. So it get just one time. I couldn't find the problem or fix way. Can you help me? Thank you.
Here is my codes:
void Start()
{
if(PlayerPrefs.GetInt("BeniHatirla")==1)
{
Debug.Log("start "+PlayerPrefs.GetInt("BeniHatirla"));
BeniHatirlaGetir();
}
}
Here is the method ı called in start:
public void BeniHatirlaGetir()
{
isim = PlayerPrefs.GetString("BeniHatirlaIsim");
sifre = PlayerPrefs.GetString("BeniHatirlaSifre");
Debug.Log("kullanici "+isim+sifre);
BeniHatirlaUniSlider.value = 1;
Debug.Log("Ogrenm Durumu"+PlayerPrefs.GetInt("OgrenimDurumuBelirleme"));
switch (PlayerPrefs.GetInt("OgrenimDurumuBelirleme"))
{
case 1:
OrtaOkulKadiTextBox.text = isim.ToString();
OrtaokulKsifreTextBox.text = sifre.ToString();
LoginPanelleri[0].SetActive(true);
break;
case 2:
LiseKadiTextBox.text = isim.ToString();
LiseKsifreTextBox.text = sifre.ToString();
LoginPanelleri[1].SetActive(true);
break;
case 3:
UniversiteKadiTextBox.text = isim.ToString();
UniversiteKsifreTextBox.text = sifre.ToString();
LoginPanelleri[2].SetActive(true);
break;
}
}
And here is the rememmer me button:
public void BeniHatırlaButon()
{
PlayerPrefs.SetInt("BeniHatirla", 1);
switch (PlayerPrefs.GetInt("OgrenimDurumuBelirleme"))
{
case 1:
PlayerPrefs.SetString("BeniHatirlaIsim", OrtaOkulKadiTextBox.text.ToString());
PlayerPrefs.SetString("BeniHatirlaSifre", OrtaokulKsifreTextBox.text.ToString());
break;
case 2:
PlayerPrefs.SetString("BeniHatirlaIsim", LiseKadiTextBox.text.ToString());
PlayerPrefs.SetString("BeniHatirlaSifre", LiseKsifreTextBox.text.ToString());
break;
case 3:
PlayerPrefs.SetString("BeniHatirlaIsim", UniversiteKadiTextBox.text.ToString());
PlayerPrefs.SetString("BeniHatirlaSifre", UniversiteKsifreTextBox.text.ToString());
break;
}
}
If you're running some debugger, it may be missing out on when it actually saves the values to disk. From the documentation for PlayerPrefs:
By default Unity writes preferences to disk during OnApplicationQuit(). In cases when the game crashes or otherwise prematuraly exits, you might want to write the PlayerPrefs at sensible 'checkpoints' in your game. This function will write to disk potentially causing a small hiccup, therefore it is not recommended to call during actual gameplay.
So if you are exiting the application prematurely through debugging it may be that you just need to call PlayerPrefs.Save() right after you try to write the values.
well I have a Hybrid Webview that is calling a page and when it does I want to be able to handle the errors using the Navigated and Navigating event. This is my code below:
<StackLayout HorizontalOptions="FillAndExpand" BackgroundColor="{Binding ThemeColor}" IsVisible="{Binding IsAdvert}">
<local:HybridWebView x:Name="hybridWebView" Navigated="webOnEndNavigating" Navigating="Webview_Navigating" Uri="{Binding Source}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</StackLayout>
Then in the .cs code where the event is is:
void webOnEndNavigating(object sender, WebNavigatedEventArgs e)
{
progress.IsVisible = false;
try
{
switch (e.Result)
{
case WebNavigationResult.Cancel:
Navigation.PopAsync();
break;
case WebNavigationResult.Failure:
var isConnected = Connectivity.NetworkAccess;
if (isConnected != NetworkAccess.Internet)
{
Navigation.PushModalAsync(new Offline());
Navigation.PopAsync();
}
break;
case WebNavigationResult.Success:
mnu.IsEmptyList = false;
break;
case WebNavigationResult.Timeout:
Navigation.PushModalAsync(new Offline());
Navigation.PopAsync();
break;
default:
Navigation.PushModalAsync(new Offline());
Navigation.PopAsync();
break;
}
}
catch
{
Navigation.PushModalAsync(new Offline());
Navigation.PopAsync();
}
}
private void Webview_Navigating(object sender, WebNavigatingEventArgs e)
{
progress.IsVisible = true;
}
I have paced breakpoints at each end every case of my switch statement and even on the entry level of my event but I am not getting anything either on the successful rendering of the site I am calling or on the failure or time out. How best Can I handle this?
According to xamarin documents:
On iOS, this HTML file resides in the Content folder of the platform
project, with a build action of BundleResource. On Android, this HTML
file resides in the Assets/Content folder of the platform project,
with a build action of AndroidAsset.
I did a test based on this sample and the method can work. So, you can check your webpage to see if it's in the right place.
For more information, you can refer to this https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/hybridwebview
I read this article about "How to play audio in the background (XAML)" and works,i played my mp3 file well,but if i try to out from app the music just stop,i thought "background audio" was to play even if the app was not focus on screen!
XAML
<Grid>
<MediaElement x:Name="musicPlayer"
Source="Assets/VIGEVANO.mp3"
AudioCategory="BackgroundCapableMedia"
CurrentStateChanged="MusicPlayer_CurrentStateChanged" />
</Grid>
CS
SystemMediaTransportControls systemControls;
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
// Hook up app to system transport controls.
systemControls = SystemMediaTransportControls.GetForCurrentView();
systemControls.ButtonPressed += SystemControls_ButtonPressed;
// Register to handle the following system transpot control buttons.
systemControls.IsPlayEnabled = true;
systemControls.IsPauseEnabled = true;
}
private void SystemControls_ButtonPressed(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
{
switch (args.Button)
{
case SystemMediaTransportControlsButton.Play:
PlayMedia();
break;
case SystemMediaTransportControlsButton.Pause:
PauseMedia();
break;
default:
break;
}
}
async void PlayMedia()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
musicPlayer.Play();
});
}
async void PauseMedia()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
musicPlayer.Pause();
});
}
What i miss?
Summary answer reached
Since Background Streaming was the main requirement so the solution reached was
Yes Check out this sample and let me know if it works for you.
Your background task first tutorial works for local mp3 files but streaming audio is a different scenario in itself
Also for streaming we used to use PhoneSM
I'm writing a windows 7 desktop C# app and I need to write code when there is a location sensor. I have this:
public string check(string stop)
{
GeoCoordinateWatcher watcher = new GeoCoordinateWatcher();
watcher.Start();
watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged);
return null;
}
static void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
{
switch (e.Status)
{
case GeoPositionStatus.Initializing:
Console.WriteLine("Working on location fix");
break;
case GeoPositionStatus.Ready:
Console.WriteLine("Have location");
break;
case GeoPositionStatus.NoData:
Console.WriteLine("No data");
break;
case GeoPositionStatus.Disabled:
Console.WriteLine("Disabled");
break;
}
MessageBox.Show("GO");
}
This is really just to see if it grabs the latitude and longitude, but I don't have a sensor and I just want to know, will this work if a laptop does have a sensor? I can't afford to get a sensor yet so I would like to have the code and move on until I can aquire one. Also, I need to stop the geocoordinatewatcher when the user logs out, so since I cant stop this in a different function, if I start another and stop that one will that stop all?These functions are called from a webapge and there are no buttons on my form. The function called when a user logs out will be stop();. And just in case someone wanted to suggest it, I can't use GeoSense.
Old question but here goes anyway:
I think your answer is not a problem with the sensor but with the scope of the watcher variable. You start the watcher then register for the event and then your watcher losses scope.
GeoCoordinateWatcher watcher = new GeoCoordinateWatcher();
public string check(string stop)
{
watcher.Start();...
I would like to use this menu through C# or F# in Win7. I even couldn't find how to call it.
In Introducing The Taskbar APIs on the MSDN magazine, it describes about how to use the Thumbnail Toolbars.
The managed equivalent does not currently appear in the Windows API
Code Pack, but it is planned to appear in a future release. In the
meantime, you can use the Windows 7 taskbar Interop Sample Library. It
contains the ThumbButtonManager class with the corresponding
CreateThumbButton and AddThumbButtons methods for controlling the
thumbnail toolbar, and also the ThumbButton class for modifying the
thumbnail button state at runtime. To receive notifications, you
register for the ThumbButton.Clicked event and override your window
procedure to dispatch the messages to the ThumbButtonManager class,
which does the dispatching magic for you. (For more details, see the
blog article Windows 7 Taskbar: Thumbnail Toolbars.)
ITaskbarList3* ptl;//Created earlier //In your window procedure:
switch (msg) {
case g_wmTBC://TaskbarButtonCreated
THUMBBUTTON buttons[2]; buttons[0].dwMask = THB_ICON|THB_TOOLTIP|THB_FLAGS; buttons[0].iId = 0;
buttons[0].hIcon = GetIconForButton(0); wcscpy(buttons[0].szTip, L"Tooltip 1"); buttons[0].dwFlags = THBF_ENABLED;
buttons[1].dwMask = THB_ICON|THB_TOOLTIP|THB_FLAGS;
buttons[1].iId = 1; buttons[1].hIcon = GetIconForButton(1);
wcscpy(buttons[0].szTip, L"Tooltip 2"); buttons[1].dwFlags = THBF_ENABLED; VERIFY(ptl->ThumbBarAddButtons(hWnd, 2,buttons));
break;
case WM_COMMAND:
if (HIWORD(wParam) == THBN_CLICKED) {
if (LOWORD(wParam) == 0)
MessageBox(L"Button 0 clicked", ...);
if (LOWORD(wParam) == 1) MessageBox(L"Button 1 clicked", ...);
}
break;
.
.
And in the second link it shows a C# sample using a wrapper library:
As always, the managed wrappers come to the rescue. The
ThumbButtonManager class (in the Windows7.DesktopIntegration project)
_thumbButtonManager = this.CreateThumbButtonManager();
ThumbButton button2 = _thumbButtonManager.CreateThumbButton(102, SystemIcons.Exclamation, "Beware of me!");
button2.Clicked += delegate
{
statusLabel.Text = "Second button clicked";
button2.Enabled = false;
};
ThumbButton button = _thumbButtonManager.CreateThumbButton(101, SystemIcons.Information, "Click me");
button.Clicked += delegate
{
statusLabel.Text = "First button clicked";
button2.Enabled = true;
};
_thumbButtonManager.AddThumbButtons(button, button2);
Note that you have tooltips and icons at your disposal to personalize the thumbnail toolbar to your application’s needs. All you need to do now is override your windows’ window procedure and call the DispatchMessage method of the ThumbButtonManager, so that it can correctly route the event to your registered event handlers (and of course, don’t forget to call the default window procedure when you’re done!):
if (_thumbButtonManager != null)
_thumbButtonManager.DispatchMessage(ref m);
base.WndProc(ref m);