I've used successfully the ContinuousScan from ZXing for xamarin using mvvmcross, I just press a button in one of my viewmodels and the camera show up. I used a delay between continuous scans I of 4000 to allow the user to read the barcodes at a slow pace. The first time enter to the view model and enter to the scanner, everything works perfect. Then I press back and i have a list with the codes, I press back again and leave the view model. I enter again to the view model and open the scanner and it just barely has focus on a barcode and it scans it two or three times without waiting for the 4000ms delay that originally was set to it. What am i missing here?
public MvxCommand ObtainCommand()
{
return new MvxCommand(delegate
{
if (HandleScanResultEvent != null) HandleScanResultEvent(this, null);
MobileBarcodeScanner.Initialize(Application);
var scanner = new MobileBarcodeScanner();
scanner.UseCustomOverlay = false;
scanner.TopText = Ts.TopTextScanContiniously;
scanner.BottomText = Ts.BottomTextScan;
var opt = new MobileBarcodeScanningOptions();
opt.DelayBetweenContinuousScans = 5000;
//Start scanning
scanner.ScanContinuously(opt, HandleScanResult);
});
}
The Handle result raise an event to the view model with the barcode read.
void HandleScanResult(ZXing.Result r)
{
if (r != null)
{
var opa = new OperationArgument
{
Operation = new Operation
{
Data r.Text,
Format = FromXingFormat(r.BarcodeFormat)
}
};
if (DataObtained != null && !(String.IsNullOrWhiteSpace(r.Text)))
{
DataObtained(this, opa);
}
}
}
the barcode scanner is opened via an mvxCommand assigned to the viewmodel. The posted code is in a class registered as a singleton.
Related
I am working on an Android application with around 3000 daily activity users.
We have an option to force the update of the app, using the Firebase RemoteConfig.
If we think that the minimum version should be, for example, 1.62, we change the remote parameter of Firebase and if the user has an older version, a Dialog appears at the beginning of the session, forcing the user to go to the Play Store and updating the app.
It's working on most of the cases, but around 1% of the users are able to use the app without seeing that Dialog.
I tried to reproduce the problem several times, but I have not been able to, the Dialog always appears to me if I have a buildVersion older than the required.
Here is the code related to this:
In the onCreate() of the MainActivity, after checking if the user has connectivity (we don't allow the use of the app if the user doesn't have connectivity)...
/**
* Initializes RemoteConfig for the project. If the connection with the remote config server
* is successfully, starts checkVersionUpdate().
*/
fun initRemoteConfig() {
val firebaseRemoteConfig = FirebaseRemoteConfig.getInstance()
val remoteConfigDefaults: MutableMap<String, Any> = HashMap()
firebaseRemoteConfig.setDefaultsAsync(remoteConfigDefaults)
firebaseRemoteConfig.fetch(IMMEDIATE_FETCH).addOnCompleteListener {
if (it.isSuccessful) {
firebaseRemoteConfig.activate().addOnCompleteListener { it2 ->
if (it2.isSuccessful) {
checkVersionUpdate()
}
}
}
}
}
The checkVersionUpdate() method, the parameter update_required has been always true...
/**
* Checks if there is a new version of SagaCollect available, if its true, forces the
* user to download it, otherwise opens LoginFragment.
*/
private fun checkVersionUpdate() {
val firebaseRemoteConfig = FirebaseRemoteConfig.getInstance()
val remoteVersionUpdate = firebaseRemoteConfig.getString(Constants.KEY_CURRENT_VERSION)
val result = VersionUtils.needsUpdate(BuildConfig.VERSION_NAME, remoteVersionUpdate) &&
firebaseRemoteConfig.getBoolean(Constants.KEY_UPDATE_REQUIRED)
if (result && !mainView.isFinishing) {
mainView.showNewVersionAvailable()
} else {
mainView.openLogin()
}
}
And the needsUpdate() method, the catch only happens around two or three times per day...
public static boolean needsUpdate(final String currentVersion, final String serverVersion) {
boolean result;
try {
final String[] preparedCurrentVersion = currentVersion.split(DOT);
final String[] preparedServerVersion = serverVersion.split(DOT);
final int leftNumberCurrentVersion = Integer.parseInt(preparedCurrentVersion[LEFT]);
final int leftNumberServerVersion = Integer.parseInt(preparedServerVersion[LEFT]);
final int rightNumberCurrentVersion = Integer.parseInt(preparedCurrentVersion[RIGHT]);
final int rightNumberServerVersion = Integer.parseInt(preparedServerVersion[RIGHT]);
result = leftNumberServerVersion > leftNumberCurrentVersion ||
(leftNumberServerVersion == leftNumberCurrentVersion &&
rightNumberServerVersion > rightNumberCurrentVersion);
} catch (final Exception e) {
result = true
}
return result;
}
Any idea on how users could be entering the app and being able to open Login and continue with the session?
We have events and we know that they open the app, so they surely pass by the onCreate() of the MainActivity.
Thank you so much.
Cheers,
Mauricio
Just a quick question about the Google speech capture inbuilt on most Android devices (not the cloud service) - see the attached image. Is there any way, either programatically or via the settings, to control how long it waits until it asks you to try again? The 'complete silence' fields in the RecognizerIntent don't seem to make any difference. On certain devices it times out very quickly and the user doesn't have enough time to start speaking.
This is the code in my test app:
public void StartSpeechToText(ISpeechResultCallback callback)
{
string rec = global::Android.Content.PM.PackageManager.FeatureMicrophone;
if (rec == "android.hardware.microphone")
{
MainActivity activity = MainActivity.CurrentActivity;
activity.Callback = callback;
var voiceIntent = new Intent(RecognizerIntent.ActionRecognizeSpeech);
//var voiceIntent = new Intent(RecognizerIntent.ActionVoiceSearchHandsFree);
voiceIntent.PutExtra(RecognizerIntent.ExtraLanguageModel, RecognizerIntent.LanguageModelFreeForm);
voiceIntent.PutExtra(RecognizerIntent.ExtraPrompt, "Speak now");
voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputCompleteSilenceLengthMillis, 1500);
voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputPossiblyCompleteSilenceLengthMillis, 1500);
voiceIntent.PutExtra(RecognizerIntent.ExtraSpeechInputMinimumLengthMillis, 15000);
voiceIntent.PutExtra(RecognizerIntent.ExtraMaxResults, 1);
voiceIntent.PutExtra(RecognizerIntent.ExtraLanguage, Java.Util.Locale.Default);
activity.StartActivityForResult(voiceIntent, VOICE);
}
}
I'm following the quickstart-android repo for ML Kit barcode scanning. In my implementation, I am noticing that in the onSuccess callback is triggered when I first launch my camera to detect barcodes, which is fine. However, the barcodes list itself is empty when I hold the camera up to valid barcodes. The onSuccess callback is called, but the barcode list is empty.
When I background the app, then foreground it, then the barcodes list starts being populated (barcodes.size() is no longer zero).
Does anyone have any idea why this would be happening?
final FirebaseVisionImage firebaseImage =
FirebaseVisionImage.fromMediaImage(image, rotation);
FirebaseVisionBarcodeDetectorOptions options = new
FirebaseVisionBarcodeDetectorOptions.Builder().setBarcodeFormats(
FirebaseVisionBarcode.FORMAT_ALL_FORMATS).build();
barcodeDetector = FirebaseVision.getInstance().getVisionBarcodeDetector(options)
barcodeDetector.detectInImage(firebaseImage).addOnSuccessListener((barcodes) ->
{
// note that the success callback is called and I do get here
// but barcode list is empty initially
for (FirebaseVisionBarcode barcode : barcodes)
{
// we never get here since barcodes.size() is 0
// until I background the app, then foreground it
// after backgrounding, then foregrounding, we start
// detecting barcodes
}
}).addOnFailureListener((exception) -> {
//TODO: handle failure
});
I am building this app, that will recognize painting and will display the info about it with the help of AR.
And I need to call multiple image target but not simultaneously, it will only call the image target if it is detected by AR camera.
*Ive tried creating many scenes with Image target on it but I cant call different imagetarget it keeps on reverting to only 1 imagetarget.
This is wat you can see in menu,
Main menu
Start AR camera(This part should have many image target but not detecting it simultaneously)
Help(how to use the app)
Exit
*Im using vuforia in creating AR
Thanks in advance for those who will help me.
This is the imagetarget and its Database
View post on imgur.com
Run the multi target scene sample. There are three target (stone, wood and road).
Each contains the TrackableBehaviour component.
Grab it and disable it in Start. If you do it in Awake it will be set back to active most likely in the Awake of the component itself or via some other manager.
public class TrackerController:MonoBehaviour
{
private IDictionary<string,TrackableBehaviours> trackers = null;
private void Start()
{
this.trackers = new Dictionary<string,TrackableBehaviour>();
var trackers = FindObjectsOfType<TrackableBehaviour>();
foreach(TrackingBehaviour tb in trackers)
{
this.trackers.Add(tb.TrackableName, tb);
tb.enabled = false;
}
}
public bool SetTracker(string name, bool value)
{
if(string.IsNullOrEmpty(name) == true){ return false; }
if(this.trackers.ContainsKey(name) == false){ return false; }
this.trackers[name].enabled = value;
return true;
}
}
The method finds all TrackableBehaviour and places them in a dictionary for easy access. The setting method return boolean, you can change it to throw exception or else.
I'm developing a codebar app for android with Xamarin and the Zxing library.
My objective was to have in the same view half of the screen with the codebar view, and the other half with the buttons to add or delete the scanned object to a list.
In MainActivity OnCreate function I have:
scanFragment = new ZXingScannerFragment();
FragmentTransaction fragmentTx = this.FragmentManager.BeginTransaction();
fragmentTx.Replace(Resource.Id.fragment, scanFragment);
fragmentTx.SetTransition(FragmentTransit.FragmentFade);
fragmentTx.Commit();
In ZXingScannerFragment OnCreate I have
frame = (FrameLayout)layoutInflater.Inflate(Resource.Layout.zxingscannerfragmentlayout, viewGroup, false);
return frame;
What I want it that, when the user scans something the view of the camera shut off, and then when the user has decided if wants to keep or discard the scanned object the camera shows again.
So I have a scann function called when the code is detected on MainActivity, who calls the OnPause method in the Zxing fragment and enables the buttons with this code:
var opts = new MobileBarcodeScanningOptions {
PossibleFormats = new List<ZXing.BarcodeFormat> {
ZXing.BarcodeFormat.All_1D,
}
};
scanFragment.StartScanning(result => {
if (result == null || string.IsNullOrEmpty(result.Text)) {
Toast.MakeText(this, "Scanning Cancelled", ToastLength.Long).Show();
return;
}
else
{
_player.Start();
RunOnUiThread(() => codBox.Text = result.Text);
RunOnUiThread(() => addBut.Enabled = true);
RunOnUiThread(() => delBut.Enabled = true);
RunOnUiThread(() => masBut.Enabled = true);
RunOnUiThread(() => menBut.Enabled = true);
RunOnUiThread(() => buttonDate.Enabled = true);
RunOnUiThread(() => finishBut.Enabled = false);
scanFragment.OnPause();
}
}, opts);
And then I have another function who calls the OnResume from Zxing fragment.
The OnPause function looks like:
base.OnPause ();
if (scanner != null)
{
frame.RemoveView(scanner);
if (!UseCustomOverlayView)
frame.RemoveView(zxingOverlay);
else if (CustomOverlayView != null)
frame.RemoveView(CustomOverlayView);
scanner.ShutdownCamera();
scanner = null;
}
The problem is:
With this code the OnPause function gives a "Only the original thread that created a view hierarchy can touch its views" Exception, but if I ignore it all works well some random time. I can take a code, camera vanishes, then add or remove object, and call camera again and all works fine 5... 10... 15 times in a row until I get a "Unhandled Exception: Java.Lang.NullPointerException" with no Idea were is being fired and no more info.
If I do something to prevent the hierarchy exception like:
if (scanner != null)
{
var myActivity = (MainActivity)this.Activity;
myActivity.RunOnUiThread(() =>
{
frame.RemoveView(scanner);
if (!UseCustomOverlayView)
frame.RemoveView(zxingOverlay);
else if (CustomOverlayView != null)
frame.RemoveView(CustomOverlayView);
});
scanner.ShutdownCamera();
scanner = null;
}
The camera vanishes, no exception is throwed but when I call the OnResume I get a static image of the last code detected.
At the end after many attempts I realized I was using a unmanaged crash as a correct behaviour of my app.
What I do is instead of calling the OnResume and OnPause functions (who have clearly objectives) of the Zxingfragment call directly scan function and stopscanning function.