Take Photo in Xamarin Android with MvvmCross - c#

I'm working on Xamarin Android project and I want to implement taking photo with MvvmCross.
Here's my code:
public class PhotoService:IPhotoService
{
private const int MaxPixelDimension = 1280;
private const int DefaultJpegQuality = 90;
private Stream imageStream;
public Stream ImageStream
{
get { return imageStream; }
set { imageStream = value; }
}
public void GetPhoto()
{
var task = Mvx.Resolve<IMvxPictureChooserTask>();
task.TakePicture(
MaxPixelDimension,
DefaultJpegQuality,
SavePicture, null);
}
private void SavePicture(Stream stream)
{
ImageStream = stream;
}
}
but in:
task.TakePicture(
MaxPixelDimension,
DefaultJpegQuality,
SavePicture,
null);
I have error:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
UPDATE
in call stack I have:
0x0 in Android.Content.Intent..ctor at /Users/builder/data/lanes/3511/501e63ce/source/monodroid/src/Mono.Android/platforms/android-24/src/generated/Android.Content.Intent.cs:1275,6 C#
0x12 in MvvmCross.Plugins.PictureChooser.Droid.MvxPictureChooserTask.TakePicture C#
0x3A in App.Services.PhotoService.PhotoService.GetPhoto at C:\app\App.Services\PhotoService\PhotoService.cs:38,4 C#
0x7 in App.ViewModels.ViewModels.MainViewModel.TakePhoto at C:\app\App.ViewModels\ViewModels\MainViewModel.cs:49,4 C#

Alternative solution you can use Media Plugin that available in nuget
https://www.nuget.org/packages/Xam.Plugin.Media/
You can use dependency service to call the takePictureAsync method from android project. With this library you can specify file name and folder path to store your image. This library can also take video using takeVideoAsync method.

I believe you need to add the MVVMCross.Pugin.PictureChooser package to your Core and platform specific projects.

Related

As from the program .NET MAUI pass AssetManager to the C++ library

The AssetManager received in C# (MAUI for Android) is accepted by the library, but does not work when trying to use it. How to pass the AssetManager correctly or how to get value of AAssetManager *pAssetManager?
C# code:
#if ANDROID
[DllImport("library.so", EntryPoint = "SetAsset")]
public static extern void SetAsset(IntPtr env, Android.Runtime.IJavaObject assetManager);
#endif
void Proc()
{
var env = Environment.EnvironmentPointer; // JNIEnv *env
AssetManager assets = Android.App.Application.Context.Assets; // jobject
SetAsset(env, assets);
}
library.so code:
void SetAsset(JNIEnv *env, jobject assetManager)
{
AAssetManager *pAssetManager = AAssetManager_fromJava(env, assetManager); // ERROR in this point
...
}

MAUI Blazor App Microsoft.CognitiveServices.Speech keyword recognition opening custom table error

I was trying to create simple service that listens for keyword from speech. I was using Microsoft.CognitiveServices.Speech ver 1.24.1 and proceeding with official documentation but got error while trying to read KeywordRecognitionodel from file, file is accessible from that path. Also tried relative and absolute path.
using Microsoft.CognitiveServices.Speech;
using Microsoft.CognitiveServices.Speech.Audio;
namespace HandyCook.Services
{
internal class KeyWordRecognizerService
{
public KeyWordRecognizerService()
{
StartRecognizing();
}
private async void StartRecognizing()
{
var audioConfig = AudioConfig.FromDefaultMicrophoneInput();
var recognizer = new KeywordRecognizer(audioConfig);
recognizer.Recognized += (s, e) =>
{
Console.WriteLine($"{e.Result.Text} DETECTED");
};
var stream = await FileSystem.Current.OpenAppPackageFileAsync("XXX.table"); //accessible
//Exception with an error code: 0x8 (SPXERR_FILE_OPEN_FAILED)
var keywordModel = KeywordRecognitionModel.FromFile(Path.Combine(FileSystem.Current.AppDataDirectory, "XXX.table"));
var result = recognizer.RecognizeOnceAsync(keywordModel);
result.Wait();
}
}
}
To reproduce the error just simply create new MAUI Blazor App, add nuget package 'Microsoft.CognitiveServices.Speech 1.24.1', add service as singleton in MauiProgram then inject in Index.razor. I'm pasting also table file and solution explorer view.
table file: https://sendanywhe.re/18U3PXF8

Xamarin Forms: Platform specific code does not show xaml file

I have a native sdk in my Xamarin Forms which does nothing. I have a xaml file behind the platform specific .cs file but the contents are not displayed.
Main file
private async void Video()
{
DependencyService.Get<InterfaceFile>().GetNativeMethod();
}
Interface file
public interface InterfaceFile
{
void GetNativeMethod();
}
Native file:
[assembly: Xamarin.Forms.Dependency(typeof(Demo))]
namespace Demo.Droid
{
public partial class Demo : InterfaceFile
{
public string GetNativeMthod()
{
/// code
}
}
}
The above platform specific code has video implementation using third party native sdks. I have xaml code behind this file.
I want to start this video call in this xaml file, which is not happening. How to bind the xaml file to .cs file?
Edit
I have tried removing the xaml code, and added only .cs file with following code(using Vidyo native sdk):
public void GetNativeMethod()
{
_vidyoConnector = new Connector(viewHandle,Connector.ConnectorViewStyle.ConnectorviewstyleDefault, 16, "warning all#VidyoConnector info#VidyoClient", "", 0);
_vidyoConnector.ShowViewAt(viewHandle, 0, 0, viewWidth, viewHeight);
_vidyoConnector.Connect(host, token, displayName, resourceId, this);
}
With above code, app crashes because frame is not defined here.
Native sdk code for Connector method:
public Connector(IntPtr viewId, ConnectorViewStyle viewStyle, uint remoteParticipants, String logFileFilter, String logFileName, ulong userData){
IntPtr nLogFileFilter = MarshalPtrToUtf8.GetInstance().MarshalManagedToNative(logFileFilter ?? string.Empty);
IntPtr nLogFileName = MarshalPtrToUtf8.GetInstance().MarshalManagedToNative(logFileName ?? string.Empty);
objPtr = VidyoConnectorConstructNative(ref viewId, viewStyle, remoteParticipants, nLogFileFilter, nLogFileName, userData);
Marshal.FreeHGlobal(nLogFileName);
Marshal.FreeHGlobal(nLogFileFilter);
VidyoConnectorSetUserDataNative(objPtr, GCHandle.ToIntPtr(GCHandle.Alloc(this, GCHandleType.Weak)));
}
Documentation reference for vidyo: https://developer.vidyo.io/#/documentation

Make a USSD call in Xamarin Crossplatform app

I want to make a USSD call in a xamarin crossplatform app using C# and i have no idea where to start. All the examples i have seen is done in java. Is it possible to successfully dial a USSD code like *270# within my app without opening the dialer? If yes, please how? I'll be very grateful for any help
To do it with Xamarin forms you have to create a custom renderer for android :
Create an interface in your shared project :
public interface IUssdRenderer
{
void StartTransaction();
}
then in your android project :
using System;
using Android.Content;
using Android.OS;
using ussd.Renderers;
[assembly: Xamarin.Forms.Dependency(typeof(IUssdRenderer))]
namespace ussd.Droid.Renderers
{
public class UssdRenderer : IUssdRenderer
{
public Android.Net.Uri createUriFromString(string ussd)
{
String uri = "tel:";
foreach (char c in ussd.ToCharArray())
{
if (c == '#')
{
uri += Android.Net.Uri.Encode("#");
}
else
{
uri += c;
}
}
return Android.Net.Uri.Parse(uri);
}
public void StartTransaction()
{
var intent = new Intent(Intent.ActionCall, createUriFromString("*270#"));
Context ctx = Xamarin.Forms.Forms.Context;
ctx.StartActivity(intent);
}
}
}
You'll also have to register you interface, I'm using prism :
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.Register< IUssdRenderer, UssdRenderer>();
}
The last bit is to make sure you have Call permissions enabled :
Right click on Android Project > Options > Android application
make sure CallPhone is selected
You may use Xamarin.Essentials PhoneDialer, to make a call, note that since USSD contains '#' you need to URL-encode it. example:
string code = "*123#";
PhoneDialer.Open(HttpUtility.UrlEncode(code));
After collecting from left and right I finally found the solution to my question with CrossMessaging plugin.
The steps are as follow:
Create your project and give the name
Install from nuget Xam.Plugins.Messaging in your project
Add below line in Android project MainActivity's OnCreate method:
CrossMessaging.Current.Settings().Phone.AutoDial = true;
Add android.permission.CALL_PHONE to the manifest file.
Make calls as follow
try
{
var phonedialer = CrossMessaging.Current.PhoneDialer;
if (phonedialer.CanMakePhoneCall)
{
//Ussd call's
phonedialer.MakePhoneCall(HttpUtility.UrlEncode("#150#"));
//For normal calls
phonedialer.MakePhoneCall("9111111111")
}
}
catch (Exception exc)
{
await DisplayAlert("Error!!!!", exc.ToString(), "ok");
}

Load file downloaded iOS app created in Unity

I'm trying to load a json file downloaded and saved in the persistentDataPath of an iOS device. The download and save works great. However I think I have big issues to load the file. In fact when I try to compile the project in Xcode I have some errors messages.
First here is my C# code :
using UnityEngine;
using System.Collections;
using System.IO;
using System.Net;
using UnityEngine.UI;
public class ReadJson : MonoBehaviour
{
public Text City;
public Text Temperature;
public Image Weather;
public Text WeatherUrl;
[System.Serializable]
public class CityInfo
{
public string name;
}
[System.Serializable]
public class CurrentCondition
{
public string date;
public string hour;
public int tmp;
public int wnd_spd;
public int wnd_gust;
public string wnd_dir;
public double pressure;
public int humidity;
public string condition;
public string icon;
public string icon_big;
}
[System.Serializable]
public class RootObject
{
public CityInfo city_info;
public CurrentCondition current_condition;
}
void Start () {
WebClient client = new WebClient();
File.Delete(Path.Combine (Application.persistentDataPath, "myjson.json"));
client.DownloadFile ("http://www.myjsonurl", Path.Combine (Application.persistentDataPath, "myjson.json"));
TextAsset asset = Resources.Load (Path.Combine (Application.dataPath + "/Documents", "myjson")) as TextAsset;
RootObject m = JsonUtility.FromJson<RootObject> (asset.text);
City.text = m.city_info.name;
Temperature.text = (m.current_condition.tmp).ToString();
}
}
And now the xcode console :
2016-10-21 17:01:20.766001 json[1404:516674] [DYMTLInitPlatform] platform initialization successful
2016-10-21 17:01:20.929950 json[1404:516508] -> registered mono modules 0xb95f70
2016-10-21 17:01:21.356590 json[1404:516508] You've implemented -[<UIApplicationDelegate> application:didReceiveRemoteNotification:fetchCompletionHandler:], but you still need to add "remote-notification" to the list of your supported UIBackgroundModes in your Info.plist.
-> applicationDidFinishLaunching()
2016-10-21 17:01:21.452967 json[1404:516508] Metal GPU Frame Capture Enabled
2016-10-21 17:01:21.453369 json[1404:516508] Metal API Validation Enabled
-> applicationDidBecomeActive()
Init: screen size 750x1334
Initializing Metal device caps
Initialize engine version: 5.3.4f1 (fdbb5133b820)
UnloadTime: 1.705875 ms
Salut/var/mobile/Containers/Data/Application/51A2490E-94EB-4904-9F2E-112AD5632A98/Documents
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 37)
NullReferenceException: A null value was found where an object instance was required.
(Filename: currently not available on il2cpp Line: -1)
Setting up 1 worker threads for Enlighten.
Thread -> id: 19f17000 -> priority: 1
If someone has an idea. Thanks a lot in advance.
The problem with your code is on this line:
TextAsset asset = Resources.Load(Path.Combine(Application.dataPath + "/Documents", "myjson")) as TextAsset;
I don't think you understand how and when to use Resources.Load. If you want to use the Resources.Load function, you must create a special folder from the Editor. This folder should be at <ProjectDirectory>/Assets/Resources. You can only put/write stuff into this folder from the Editor. You can't do it after build on iOS. It becomes read only after you build it. This special folder can then be read with the Resources.Load function.
Replacing:
TextAsset asset = Resources.Load(Path.Combine(Application.dataPath + "/Documents", "myjson")) as TextAsset;
with
string text = File.ReadAllText(Path.Combine(Application.persistentDataPath, "myjson.json"));
RootObject m = JsonUtility.FromJson<RootObject>(text);
City.text = m.city_info.name;
Temperature.text = (m.current_condition.tmp).ToString();
Should solve your problem.
Another API that should not be using is WebClient. Unless you have a good reason to use that, you shouldn't. You should either use the WWW or UnityWebRequest(newer and recommended) API.
This is what your code should look like without WebClient:
void Start()
{
StartCoroutine(DownloadAndloadJson());
}
IEnumerator DownloadAndloadJson()
{
string url = "http://www.myjsonurl";
UnityWebRequest www = UnityWebRequest.Get(url);
yield return www.Send();
if (www.isError)
{
Debug.Log(www.error);
}
else
{
//Sucessfully downloaded the Json File
Debug.Log("Json: " + www.downloadHandler.text);
string jsonFile = www.downloadHandler.text;
//Delete old json file. Don't know why but this was in your original code
File.Delete(Path.Combine(Application.persistentDataPath, "myjson.json"));
//Save the downloaded data as File
File.WriteAllText(Path.Combine(Application.persistentDataPath, "myjson.json"), jsonFile);
//Load the downloaded data
string text = File.ReadAllText(Path.Combine(Application.persistentDataPath, "myjson.json"));
Debug.Log(text);
RootObject m = JsonUtility.FromJson<RootObject>(text);
City.text = m.city_info.name;
Temperature.text = (m.current_condition.tmp).ToString();
}
}
If you have problems please update to Unity 5.4. The UnityWebRequest API should be used for this and it was introduced in 5.3 but bugs were fixed in 5.4. You need using UnityEngine.Networking; to use UnityWebRequest.

Categories

Resources