I am using xamarin-bluetooth-le to make BluetoothLE client side on Xamarin.
I searched few of BluetoothLE package (sample code is work fine).
Thus, I have choosed xamarin-bluetooth-le.
In fact, sample code work fine.
However, I am simplify sample code without view, becuse I am not need View and binding is not need.
However xamarin-bluetooth-le does not scan device by the simplify code.
First question:
In sample of xamarin-bluetooth-le, an event named DeviceDiscovered is need assign two times?(one is DeviceListViewModel constructor, the other is scan method).
Second(main) question:
Why xamarin-bluetooth-le does not scan device by below codes?
Environment is
Visual Studio 2019 16.10.0
Xamarin 16.10.000.228
Plugin.BLE 2.1.2
Other newest
Below is code:
BluetoothClient.cs
using Plugin.BLE;
using Plugin.BLE.Abstractions.Contracts;
using Plugin.BLE.Abstractions.EventArgs;
using Plugin.BLE.Abstractions.Extensions;
using System;
using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
namespace PlugInBLETest.NetowrkModels
{
public class BluetoothBLEClient
{
private IAdapter Adapter;
private IBluetoothLE Current;
public ObservableCollection<IDevice> DeviceList { get; }
private CancellationTokenSource CancelSource;
public BluetoothBLEClient()
{
Current = CrossBluetoothLE.Current;
Adapter = CrossBluetoothLE.Current.Adapter;
Adapter.DeviceDiscovered += OnDeviceDiscovered;
Adapter.ScanTimeoutElapsed += OnScanTimeoutElapsed;
Adapter.DeviceDisconnected += OnDeviceDisconnected;
Adapter.DeviceConnectionLost += OnDeviceConnectionLost;
DeviceList = new ObservableCollection<IDevice>();
}
public async Task SearchDevices()
{
if (Current.State == BluetoothState.Off)
{
return;
}
else
{
DeviceList.Clear();
foreach (var connectedDevice in Adapter.ConnectedDevices)
{
try
{
await connectedDevice.UpdateRssiAsync();
}
catch (Exception ex)
{
return;
}
}
CancelSource = new CancellationTokenSource();
Adapter.ScanMode = ScanMode.LowLatency;
Adapter.ScanTimeout = 30000;
//Adapter.DeviceDiscovered += (s, a) => DeviceList.Add(a.Device);
Adapter.DeviceDiscovered += (s, a) =>
{
DeviceList.Add(a.Device);
};
await Adapter.StartScanningForDevicesAsync(CancelSource.Token);
var temp = DeviceList.Count;
}
return;
}
private void OnDeviceConnectionLost(object sender, DeviceErrorEventArgs e)
{
}
private void OnDeviceDisconnected(object sender, DeviceEventArgs e)
{
}
private void OnScanTimeoutElapsed(object sender, EventArgs e)
{
}
private void OnDeviceDiscovered(object sender, DeviceEventArgs args)
{
}
}
}
AndroidManifext.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.pluginbletest">
<uses-sdk android:targetSdkVersion="30" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<application android:label="PlugInBLETest.Android" android:theme="#style/MainTheme"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
Xamarin.Essentials has a permissions feature that will allow you to check for and request permission for access to the location data
After Marshmallow you have to prompt for the user for permission -> https://devblogs.microsoft.com/xamarin/requesting-runtime-permissions-in-android-marshmallow/
Related
Im trying to launch an app that I've created from another app that Im working on right now. The thing is I've been searching throught the internet and found something but it did not work so Im seeking help in here.
This is what I've done on the app I want to launch from :
On my xaml.cs :
public async void GoToDigDitApp(object sender, EventArgs e)
{
var appname = "digdit://";
var result = await DependencyService.Get<IAppHandler>().LaunchApp(appname);
}
I created an Interface:
public interface IAppHandler
{
Task<bool> LaunchApp(string uri);
}
In the Android project:
[assembly: Dependency(typeof(OpenAppAndroid))]
namespace SupervisingApp.Droid
{
[Activity(Label = "OpenAppAndroid")]
public class OpenAppAndroid : Activity, IAppHandler
{
public Task<bool> LaunchApp(string uri)
{
bool result = false;
try
{
var aUri = Android.Net.Uri.Parse(uri.ToString());
var intent = new Intent(Intent.ActionView, aUri);
Android.App.Application.Context.StartActivity(intent);
result = true;
}
catch (ActivityNotFoundException)
{
result = false;
}
return Task.FromResult(result);
}
}
}
And This is the app I want to launch manifest :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.Tab2" android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<application android:label="Dig Dit" android:icon="#drawable/ic_launcher">
<activity android:icon="#drawable/ic_launcher" android:label="Dig Dit" android:name="digdit.urlentryclass">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="digdit" />
</intent-filter>
</activity>
</application>
</manifest>
For now Im only intressted by the Android part and it doesn't seem to work. I hope you guys can help me out.
You could use PackageManager.GetLaunchIntentForPackage.
Try the code below. com.companyname.app2 is the package name of App2.
Intent intent = PackageManager.GetLaunchIntentForPackage("com.companyname.app2");
StartActivity(intent);
Updated:
Create a interface:
public interface IDpendencyService
{
Task<bool> Launch(string stringUri);
}
Implemention of Android:
public class DependencyImplementation : Activity, IDpendencyService
{
public Task<bool> Launch(string stringUri)
{
Intent intent = Android.App.Application.Context.PackageManager.GetLaunchIntentForPackage(stringUri);
if (intent != null)
{
intent.AddFlags(ActivityFlags.NewTask);
Forms.Context.StartActivity(intent);
return Task.FromResult(true);
}
else
{
return Task.FromResult(true);
}
}
}
Usage of MainPage:
<StackLayout>
<!-- Place new controls here -->
<Label
FontAttributes="Bold"
FontSize="Large"
HorizontalOptions="Center"
Text="Welcome to App1!"
VerticalOptions="CenterAndExpand" />
<Button x:Name="GotoApp2" Text="GotoApp2" Clicked="GotoApp2_Clicked"></Button>
</StackLayout>
private void GotoApp2_Clicked(object sender, EventArgs e)
{
DependencyService.Get<IDpendencyService>().Launch("com.companyname.app2");
}
I have upload on GitHub, you could download from the StartAnotherApp_Xamarin.forms/App1 folder for reference.
https://github.com/WendyZang/Test.git
You can open you app from xamarin.forms
Device.BeginInvokeOnMainThread(() =>
{
Xamarin.Forms.Device.OpenUri(new Uri("digdit://555-1111"));
});
I have a Xamarin app where I implemented a service to do some printing. I create that service on UWP app because it needs some dependencies of it.
UWP Service:
public class PrintUWPService
{
PrintManager printmgr = PrintManager.GetForCurrentView();
PrintDocument PrintDoc;
PrintDocument printDoc;
PrintTask Task;
private Windows.UI.Xaml.Controls.WebView ViewToPrint = new Windows.UI.Xaml.Controls.WebView();
public PrintUWPService()
{
printmgr.PrintTaskRequested += Printmgr_PrintTaskRequested;
}
public async void Print(WebView viewToPrint, string htmlSource)
{
ViewToPrint.NavigateToString(htmlSource);
if (PrintDoc != null)
{
printDoc.GetPreviewPage -= PrintDoc_GetPreviewPage;
printDoc.Paginate -= PrintDoc_Paginate;
printDoc.AddPages -= PrintDoc_AddPages;
}
printDoc = new PrintDocument();
try
{
printDoc.GetPreviewPage += PrintDoc_GetPreviewPage;
printDoc.Paginate += PrintDoc_Paginate;
printDoc.AddPages += PrintDoc_AddPages;
var showprint = await PrintManager.ShowPrintUIAsync();
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
}
PrintDoc = null;
GC.Collect();
}
private void Printmgr_PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args)
{
var deff = args.Request.GetDeferral();
Task = args.Request.CreatePrintTask("Grocery List", OnPrintTaskSourceRequested);
deff.Complete();
}
async void OnPrintTaskSourceRequested(PrintTaskSourceRequestedArgs args)
{
var def = args.GetDeferral();
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
args.SetSource(printDoc.DocumentSource);
});
def.Complete();
}
private void PrintDoc_AddPages(object sender, AddPagesEventArgs e)
{
printDoc.AddPage(ViewToPrint);
printDoc.AddPagesComplete();
}
private void PrintDoc_Paginate(object sender, PaginateEventArgs e)
{
PrintTaskOptions opt = Task.Options;
printDoc.SetPreviewPageCount(1, PreviewPageCountType.Final);
}
private void PrintDoc_GetPreviewPage(object sender, GetPreviewPageEventArgs e)
{
printDoc.SetPreviewPage(e.PageNumber, ViewToPrint);
}
}
}
Then I create interface for it:
public interface IPrintUWPService
{
void Print(WebView viewToPrint, string htmlSource);
}
Now inside a class of my shared project I want to call this service as:
private readonly IPrintUWPService _printService = DependencyService.Get<IPrintUWPService>();
But it does not work. it says:
IPrintUWPService does not exist in the current context
So I try to access to UWP class as:
using MyCompany.ProjectName.App.UWP
But it says that "UWP" namespace does not exist. What am I doing wrong? is not possible call service on UWP project inside shared project? Regards
Call UWP DependencyService on Shared project
As #Jason mentioned in above comment, you need declare the interface in the Xamarin Forms project and implement it in the UWP client project.
And please note, after implementing the interface in each platform project, the platform implementations must be registered with the DependencyService, so that Xamarin.Forms can locate them at runtime. Use DependencyAttribute like the following.
[assembly: Dependency(typeof(UWP Client namesapce))]
This is my code please check it and give me solution. i have use also this both dependancy.
i have use fitnessoption to get permission from user.
after getting permission i also subscibe the user and then i readd daily step data from google fitness api using readData().
i also check the activity recognization permission of manifest file.
implementation 'com.google.android.gms:play-services-fitness:18.0.0'
implementation 'com.google.android.gms:play-services-auth:18.0.0'
//manifest file
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
public class HomeFragement extends Fragment{
// FitnessOptions create
FitnessOptions fitnessOptions = FitnessOptions.builder()
.addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
.addDataType(DataType.AGGREGATE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
.build();
GoogleSignInAccount account = GoogleSignIn.getAccountForExtension(getActivity(), fitnessOptions);
if (!GoogleSignIn.hasPermissions(account, fitnessOptions)) {
GoogleSignIn.requestPermissions(
getActivity(),
REQUEST_OAUTH_REQUEST_CODE,
account,
fitnessOptions);
} else {
subscribe();
}
// subscribe the google api
public void subscribe() {
// To create a subscription, invoke the Recording API. As soon as the subscription is
// active, fitness data will start recording.
Fitness.getRecordingClient(getActivity(), GoogleSignIn.getLastSignedInAccount(getContext()))
.subscribe(DataType.TYPE_STEP_COUNT_CUMULATIVE)
.addOnCompleteListener(
new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.i(TAG, "Permission Give Successfully!");
} else {
Log.w(TAG, "There was a problem subscribing.", task.getException());
}
}
});
}
// read daily step data
private void readData() {
Fitness.getHistoryClient(getActivity(), GoogleSignIn.getLastSignedInAccount(getContext()))
.readDailyTotal(DataType.TYPE_STEP_COUNT_DELTA)
.addOnSuccessListener(
new OnSuccessListener<DataSet>() {
#Override
public void onSuccess(DataSet dataSet) {
long total =
dataSet.isEmpty()
? 0
: dataSet.getDataPoints().get(0).getValue(Field.FIELD_STEPS).asInt();
txtTodayStep.setText(String.valueOf(total));
txtTodayCoin.setText(String.valueOf(new DecimalFormat("#.##").format(((int)(total)/1000f))));
Log.i(TAG, "Total steps: " + total);
}
})
.addOnFailureListener(
new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(TAG, "There was a problem getting the step count.", e);
}
});
}
}
This is my code and what is problem please tell me.
I want to use a custom IBehavior to be able to show/hide the StatusBar from XAML in a Universal app targeted at Windows Phone 8.1.
The code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xaml.Interactivity;
using Windows.ApplicationModel;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
namespace test.Behaviors
{
public class StatusBarBehavior : DependencyObject, IBehavior
{
public DependencyObject AssociatedObject { get; private set; }
public void Attach(DependencyObject associatedObject) { }
public void Detach() { }
public StatusBarBehavior()
{
}
public bool Show
{
get { return Convert.ToBoolean(GetValue(ShowProperty)); }
set { SetValue(ShowProperty, value); }
}
public static readonly DependencyProperty ShowProperty =
DependencyProperty.Register("Show",
typeof(object),
typeof(StatusBarBehavior),
new PropertyMetadata(null, OnIsVisibleChanged));
private static async void OnIsVisibleChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var statusBar = StatusBar.GetForCurrentView();
if (statusBar == null || e == null || e.NewValue == null || DesignMode.DesignModeEnabled)
return;
if (Convert.ToBoolean(e.NewValue))
await statusBar.ShowAsync();
else
await statusBar.HideAsync();
}
}
}
XAML:
<Page
x:Class="test.TestPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:test"
xmlns:behavior="using:test.Behaviors"
xmlns:i="using:Microsoft.Xaml.Interactivity"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<i:Interaction.Behaviors>
<behavior:StatusBarBehavior Show="False"/>
</i:Interaction.Behaviors>
<!-- page content -->
</Page>
The Behaviors SDK (12.0) has been added as a reference to the project.
Unfortunatly in Visual Studio 2013 (Community edition, Update 4), the design window for the page in question shows an error:
COMException: Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))
StackTrace: Empty
InnerException: None
However, the StatusBarBehavior works perfectly fine when I deploy the app on a device, no errors are thrown.
Is there a way to fix this error? Having the design window is quite necessary to preview the layout of the pages...
Changing the OnVisibleChanged event to
private static async void OnIsVisibleChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
if (DesignMode.DesignModeEnabled) { return; }
var statusBar = StatusBar.GetForCurrentView();
if (statusBar == null || e == null || e.NewValue == null)
return;
if (Convert.ToBoolean(e.NewValue))
await statusBar.ShowAsync();
else
await statusBar.HideAsync();
}
fixes the issue. I assume StatusBar.GetForCurrentView() throws an error in the design view.
I'm trying to understand how Caliburn.Micro works with Windows Phone (and MVVM in general) so I created a basic Windows Phone Application, installed Caliburn.Micro NuGet package (v1.2.0 - the latest for now) and followed the few instructions here and there. So, I ended up with:
WMAppManifest.xml
<DefaultTask Name ="_default" NavigationPage="Views/HomeView.xaml"/>
Framework/AppBootstrapper.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using Caliburn.Micro;
using MyCaliburn.PhoneUI.ViewModels;
namespace MyCaliburn.PhoneUI.Framework
{
public class AppBootstrapper : PhoneBootstrapper
{
PhoneContainer container;
protected override void Configure()
{
container = new PhoneContainer(RootFrame);
container.RegisterPhoneServices();
container.Singleton<HomeViewModel>();
}
protected override void OnUnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
if (Debugger.IsAttached)
{
Debugger.Break();
e.Handled = true;
}
else
{
MessageBox.Show("An unexpected error occured, sorry about the troubles.", "Oops...", MessageBoxButton.OK);
e.Handled = true;
}
base.OnUnhandledException(sender, e);
}
protected override object GetInstance(Type service, string key)
{
return container.GetInstance(service, key);
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
return container.GetAllInstances(service);
}
protected override void BuildUp(object instance)
{
container.BuildUp(instance);
}
}
}
ViewModels/HomeViewModel.cs
using Caliburn.Micro;
namespace MyCaliburn.PhoneUI.ViewModels
{
public class HomeViewModel : Screen
{
public HomeViewModel()
{
//DisplayName = "Home";
}
}
}
View/HomeView.xaml.cs (the XAML page is the default Window Phone Portrait Page)
using Microsoft.Phone.Controls;
namespace MyCaliburn.PhoneUI.Views
{
public partial class HomeView : PhoneApplicationPage
{
public HomeView()
{
InitializeComponent();
}
}
}
App.xaml
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyCaliburn.PhoneUI.App"
xmlns:Framework="clr-namespace:MyCaliburn.PhoneUI.Framework">
<!--Application Resources-->
<Application.Resources>
<Framework:AppBootstrapper x:Key="bootstrapper" />
</Application.Resources>
</Application>
App.xaml.cs
using System.Windows;
namespace MyCaliburn.PhoneUI
{
public partial class App : Application
{
/// <summary>
/// Constructor for the Application object.
/// </summary>
public App()
{
// Standard Silverlight initialization
InitializeComponent();
}
}
}
Now, when I hit F5, the application runs and exits without showing any page or exception and doesn't hit any breakpoints that I sit.
Can anyone tells me what's missing in my code which prevents the application from running?
Thanks in advance.
Many times when I end up with an app that does not start - it turns out that due to some refactoring the App class is not the startup object any more. Right-click on the project in solution explorer, go to properties/Application and make sure Startup object is set correctly.