I recently just started programming and developing app. I would appreciate if anybody can help me. I had did the QR scanner with ZXing and are able to display the result but i would like it to open the browser automatically if an URL is detected from the QR code
The following is my code for my Scanner Activity:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.Support.V7.App;
using Android.Views;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Widget;
using Android.Gms.Vision.Barcodes;
using Android.Gms.Vision;
using Android.Graphics;
using Android.Content.PM;
using Android.Support.V4.App;
using Android;
using static Android.Gms.Vision.Detector;
using Android.Util;
namespace com.xamarin.sample.splashscreen
{
[Activity(Label = "Scanner")]
public class Scanner : AppCompatActivity,ISurfaceHolderCallback, IProcessor
{
SurfaceView cameraPreview;
TextView txtResult;
BarcodeDetector barcodeDetector;
CameraSource cameraSource;
const int RequestCameraPermissionID = 1001;
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
{
switch(requestCode)
{
case RequestCameraPermissionID:
{
if (grantResults[0]==Permission.Granted)
{
if (ActivityCompat.CheckSelfPermission(ApplicationContext, Manifest.Permission.Camera) != Android.Content.PM.Permission.Granted)
{
ActivityCompat.RequestPermissions(this, new string[]
{
Manifest.Permission.Camera
}, RequestCameraPermissionID);
return;
}
try
{
cameraSource.Start(cameraPreview.Holder);
}
catch (InvalidOperationException)
{
}
}
}
break;
}
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Scanner);
cameraPreview = FindViewById<SurfaceView>(Resource.Id.cameraPreview);
txtResult = FindViewById<TextView>(Resource.Id.txtResult);
barcodeDetector = new BarcodeDetector.Builder(this)
.SetBarcodeFormats(BarcodeFormat.QrCode).Build();
cameraSource = new CameraSource.Builder(this, barcodeDetector)
.SetRequestedPreviewSize(640, 480).Build();
cameraPreview.Holder.AddCallback(this);
barcodeDetector.SetProcessor(this);
}
public void SurfaceChanged(ISurfaceHolder holder, [GeneratedEnum] Format format, int width, int height)
{
}
public void SurfaceCreated(ISurfaceHolder holder)
{
if (ActivityCompat.CheckSelfPermission(ApplicationContext, Manifest.Permission.Camera) != Android.Content.PM.Permission.Granted)
{
ActivityCompat.RequestPermissions(this, new string[]
{
Manifest.Permission.Camera
}, RequestCameraPermissionID);
return;
}
try
{
cameraSource.Start(cameraPreview.Holder);
}
catch (InvalidOperationException)
{
}
}
public void SurfaceDestroyed(ISurfaceHolder holder)
{
cameraSource.Stop();
}
public void ReceiveDetections(Detections detections)
{
SparseArray qrcodes = detections.DetectedItems;
if(qrcodes.Size()!=0)
{
txtResult.Post(() =>
{
Vibrator vib = (Vibrator)GetSystemService(Context.VibratorService);
vib.Vibrate(1000);
txtResult.Text = ((Barcode)qrcodes.ValueAt(0)).RawValue;
});
}
}
public void Release()
{
}
}`enter code here`
}`enter code here`
I would like it to open the browser automatically if an URL is detected from the QR code
When you get the ZXing.Result from the QR code, you could use Patterns.WebUrl.Matcher method to confirm whether this is a URL.
When you use Patterns.WebUrl.Matcher(result.Text).Matches() method, this regular expression pattern to match most part of RFC 3987 Internationalized URLs, aka IRIs.
Code like this :
private void HandleScanResult(ZXing.Result result)
{
string msg = "";
if (result != null && !string.IsNullOrEmpty(result.Text))
msg = "Found Barcode: " + result.Text;
else
msg = "Scanning Canceled!";
Intent resultIntent = new Intent();
Bundle bundle = new Bundle();
bundle.PutString("result", result.Text);
resultIntent.PutExtras(bundle);
this.SetResult(Result.Ok, resultIntent);
if (Patterns.WebUrl.Matcher(result.Text).Matches())
{
//If this result get from the QR code is an URL, open the browse.
Intent intent = new Intent();
intent.SetAction("android.intent.action.VIEW");
Android.Net.Uri content_url = Android.Net.Uri.Parse(result.Text);
intent.SetData(content_url);
StartActivity(intent);
}
else
{
this.RunOnUiThread(() => Toast.MakeText(this, msg, ToastLength.Short).Show());
}
}
Related
I already got a QR/Barcode Scanner which is working. But I have one problem. The scanner is only reading QR-Codes which contains an url but I want to scan QR-Codes with only text. Does somebody know what the problem could be?
the used library:
implementation 'com.journeyapps:zxing-android-embedded:3.4.0'
method:
private void scanCode() {
IntentIntegrator integrator = new IntentIntegrator(this);
integrator.setCaptureActivity(CaptureAct.class);
integrator.setOrientationLocked(false);
integrator.setDesiredBarcodeFormats(IntentIntegrator.ALL_CODE_TYPES);
integrator.setPrompt("Scanning Code");
integrator.initiateScan();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
...
}
hello you need to use follow configuration
compileSdkVersion 28 // Android 9 (API level 28)
minSdkVersion 24 // Android 7.0 (API level 24)
use dependency of google vision in build.gradle of app
implementation 'com.google.android.gms:play-services-vision:17.0.2'
this is the code for scan the qr code
cameraViewQR = findViewById(R.id.cameraView);
cameraViewQR.setZOrderMediaOverlay(true);
qrHolderScreen = cameraViewQR.getHolder();
barcodeQR = new BarcodeDetector.Builder(this)
.setBarcodeFormats(Barcode.QR_CODE)
.build();
if (!barcodeQR.isOperational()) {
Toast.makeText(getApplicationContext(), "Problem Occurred in Setup", Toast.LENGTH_SHORT).show();
this.finish();
}
cameraSourcePhone = new CameraSource.Builder(this, barcodeQR)
.setFacing(CameraSource.CAMERA_FACING_BACK)
.setRequestedFps(24)
.setAutoFocusEnabled(true)
.setRequestedPreviewSize(480, 480)
.build();
cameraViewQR.getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
if (ContextCompat.checkSelfPermission(ScanActivity.this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
cameraSourcePhone.start(cameraViewQR.getHolder());
}
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
barcodeQR.setProcessor(new Detector.Processor<Barcode>() {
#Override
public void release() {
}
#Override
public void receiveDetections(Detector.Detections<Barcode> detections) {
final SparseArray<Barcode> barcode = detections.getDetectedItems();
if (barcode.size() > 0) {
Intent intent = new Intent();
intent.putExtra("QRCODE", barcode.valueAt(0));
setResult(RESULT_OK, intent);
finish();
}
}
});
I'm trying to develop a mobile app in Xamarin Forms...One of the functionalities is text recognition. I need to recognize the text and then send it to another page (xaml). So i made an activity where it does recognize the text but i don't know how to return the string "Resultados" (Results). I tried to do a little search and many suggested that the "OnActivityResult" should return the values...but it doesnt get triggered.
Can anyone help me out what i am doing wrong?
TextRecognition.cs - activity(android)
public class TextRecognition : AppCompatActivity, ISurfaceHolderCallback, IProcessor, ITextRecognition
{
private SurfaceView cameraView;
private TextView textView;
private CameraSource cameraSource;
public string Resultados;
private const int RequestCameraPermissionID = 1001;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Main);
cameraView = FindViewById<SurfaceView>(Resource.Id.surface_view);
textView = FindViewById<TextView>(Resource.Id.txtview);
TextRecognizer textRecognizer = new TextRecognizer.Builder(ApplicationContext).Build();
if (!textRecognizer.IsOperational)
{
Log.Error("Main Activity", "Detector dependencies are not yet available");
}
else
{
cameraSource = new CameraSource.Builder(ApplicationContext, textRecognizer)
.SetFacing(CameraFacing.Back)
.SetRequestedFps(2.0f)
.SetRequestedPreviewSize(1280, 1024)
.SetAutoFocusEnabled(true)
.Build();
cameraView.Holder.AddCallback(this);
textRecognizer.SetProcessor(this);
}
Android.Widget.Button logonButton = FindViewById<Android.Widget.Button>(Resource.Id.button_send);
logonButton.Click += delegate {
button_OnClick();
};
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
switch (requestCode)
{
case RequestCameraPermissionID:
{
if (grantResults[0] == Android.Content.PM.Permission.Granted)
{
cameraSource.Start(cameraView.Holder);
}
}
break;
}
}
public void SurfaceChanged(ISurfaceHolder holder, [GeneratedEnum] Format format, int width, int height)
{
}
public void SurfaceCreated(ISurfaceHolder holder)
{
if (ActivityCompat.CheckSelfPermission(ApplicationContext, Manifest.Permission.Camera) != Android.Content.PM.Permission.Granted)
{
ActivityCompat.RequestPermissions(this, new string[]
{
Android.Manifest.Permission.Camera
}, RequestCameraPermissionID);
return;
}
cameraSource.Start(cameraView.Holder);
}
public void SurfaceDestroyed(ISurfaceHolder holder)
{
cameraSource.Stop();
}
public void ReceiveDetections(Detections detections)
{
SparseArray items = detections.DetectedItems;
if (items.Size() != 0)
{
textView.Post(() =>
{
StringBuilder strBuilder = new StringBuilder();
for (int i = 0; i < items.Size(); i++)
{
strBuilder.Append(((TextBlock)items.ValueAt(i)).Value);
strBuilder.Append("\n");
}
textView.Text = strBuilder.ToString();
Resultados = strBuilder.ToString();
});
}
}
async void button_OnClick()
{
Toast.MakeText(this, "Hello from " + Resultados, ToastLength.Long).Show();
Intent data = new Intent(this, typeof(TextRecognition));
SetResult(Result.Ok, data);
Finish();
}
public void Release()
{
}
public string LaunchActivityInAndroid()
{
Activity activity = Forms.Context as Activity;
var intent = new Intent(Forms.Context, typeof(TextRecognition));
activity.StartActivityForResult(intent, Convert.ToInt32(Result.Ok));
return Resultados;
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
switch(resultCode)
{
case Result.Ok:
break;
}
Finish();
}
public interface ITextRecognition
{
}
}
I tried to do a little search and many suggested that the "OnActivityResult" should return the values...but it doesnt get triggered.
You are using OnActivityResult a bit wrong. For example, if you have two Activity, ActivityA and ActivityB, OnActivityResult method in ActivityA, ActivityB need return some value to ActivityA, we can use activityA.StartActivityForResult() to open ActivityB,
ActivityB Use SetResult method to send data to ActivityA.
public class ActivityB: Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Main);
Intent intent = new Intent();
intent.PutExtra("respond", "Hello,Alice!I'm Bob.");
SetResult(Result.Ok, intent);
}
}
Then OnActivityResultwill be triggered in the ActivityA.
I need to recognize the text and then send it to another page (xaml)
If you want to send data from Activity to Forms pages, You can use MessagingCenter to achieve it.
In Activity, we can use following code to send it.
MessagingCenter.Send<App, string>(App.Current as App, "OpenPage", "You send message:" + Resultados);
In the xamarin forms pages, you can use following code to get it.
MessagingCenter.Subscribe<App, string>(App.Current, "OpenPage", (snd, arg) =>
{
var getValue = arg;
});
Here is a link about MessagingCenter.
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/messaging-center
===========update===========
I write a scan demo. Here is running gif.
Here is interface about dependenceService.
public interface ITextRecognition
{
void LaunchActivityInAndroid();
}
Here is achievement about dependenceService.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.Graphics;
using Android.OS;
using Android.Runtime;
using Android.Support.V7.App;
using Android.Views;
using Android.Widget;
using FormsTextRecognizer.Droid;
using Xamarin.Forms;
using static Android.Gms.Vision.Detector;
using Android.Gms.Vision;
using Android.Gms.Vision.Texts;
using Android.Support.V4.App;
using Android;
using Android.Content.PM;
using Android.Util;
[assembly: Dependency(typeof(TextRecognition))]
namespace FormsTextRecognizer.Droid
{
[Activity(Label = "ScanActivity", Theme = "#style/Theme.AppCompat.Light.NoActionBar")]
public class TextRecognition : AppCompatActivity, ITextRecognition, ISurfaceHolderCallback, IProcessor
{
// private CameraSource cameraSource;
private SurfaceView cameraView;
TextRecognizer textRecognizer;
private const int RequestCameraPermissionID = 1001;
private CameraSource cameraSource;
public string Resultados;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Main);
cameraView = FindViewById<SurfaceView>(Resource.Id.surface_view);
Android.Widget.Button logonButton = FindViewById<Android.Widget.Button>(Resource.Id.button_send);
textRecognizer = new TextRecognizer.Builder(Android.App.Application.Context).Build();
// Android.Gms.Vision.Frame frame = new Android.Gms.Vision.Frame.Builder().SetBitmap(bitmap).Build();
if (!textRecognizer.IsOperational)
{
Log.Error("Main Activity", "Detector dependancies are not yet available");
}
else
{
cameraSource = new CameraSource.Builder(ApplicationContext, textRecognizer)
.SetFacing(CameraFacing.Back)
.SetRequestedFps(2.0f)
.SetRequestedPreviewSize(1920, 1080)
.SetAutoFocusEnabled(true)
.Build();
cameraView.Holder.AddCallback(this);
textRecognizer.SetProcessor(this);
}
logonButton.Click += LogonButton_Click;
}
private void LogonButton_Click(object sender, EventArgs e)
{
// throw new NotImplementedException();
Toast.MakeText(this, Resultados, ToastLength.Short).Show();
MessagingCenter.Send<App, string>(App.Current as App, "OpenPage", "You send message:" + Resultados);
Finish();
}
public void LaunchActivityInAndroid()
{
//string ScanText = "";
Activity activity = Forms.Context as Activity;
var intent = new Intent(Forms.Context, typeof(TextRecognition));
activity.StartActivity(intent);
// activity.StartActivityForResult(intent, Convert.ToInt32(Result.Ok));
// return Resultados;
}
public void ReceiveDetections(Detections detections)
{
//throw new NotImplementedException();
SparseArray items = detections.DetectedItems;
if (items.Size() != 0)
{
StringBuilder strBuilder = new StringBuilder();
for (int i = 0; i < items.Size(); i++)
{
strBuilder.Append(((TextBlock)items.ValueAt(i)).Value);
strBuilder.Append("\n");
}
// textView.Text = strBuilder.ToString();
Resultados = strBuilder.ToString();
// });
}
}
public void Release()
{
// throw new NotImplementedException();
}
public void SurfaceChanged(ISurfaceHolder holder, [GeneratedEnum] Format format, int width, int height)
{
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
{
switch (requestCode)
{
case RequestCameraPermissionID:
{
if (grantResults[0] == Permission.Granted)
{
cameraSource.Start(cameraView.Holder);
}
}
break;
}
}
public void SurfaceCreated(ISurfaceHolder holder)
{
//throw new NotImplementedException();
if (ActivityCompat.CheckSelfPermission(ApplicationContext, Manifest.Permission.Camera) != Android.Content.PM.Permission.Granted)
{
//Request Permission
ActivityCompat.RequestPermissions(this, new string[] {
Android.Manifest.Permission.Camera
}, RequestCameraPermissionID);
return;
}
cameraSource.Start(cameraView.Holder);
}
public void SurfaceDestroyed(ISurfaceHolder holder)
{
cameraSource.Stop();
}
}
}
Here is Forms page background code.
[DesignTimeVisible(false)]
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
MessagingCenter.Subscribe<App, string>(App.Current, "OpenPage", (snd, arg) =>
{
scanLabel.Text = arg;
});
}
private void Button_Clicked(object sender, EventArgs e)
{
DependencyService.Get<ITextRecognition>().LaunchActivityInAndroid();
}
}
Here is my demo, you can refer to it.
https://github.com/851265601/FormsTextRecognizer
I'm trying to develop an Android app that can scan QR codes. But the problem is, it only auto focus on the QR code but not returning any results. Is there a way to fix this?
I'm using zxing libraries.
Hello guys, can someone help me?
I guess you dont have onActivityResult in your code and that is why you cant capture and return any result.
So I am attaching my work and it would help you.
cameraView = (SurfaceView) v.findViewById(R.id.cameraView);
textResult = (TextView) v.findViewById(R.id.textView);
barcodeDetector = new BarcodeDetector.Builder(v.getContext())
.setBarcodeFormats(Barcode.QR_CODE)
.build();
cameraSource = new CameraSource.Builder(v.getContext(), barcodeDetector)
.setRequestedPreviewSize(640, 640).build();
cameraView.getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (ActivityCompat.checkSelfPermission(v.getContext(), android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
//Request permission
ActivityCompat.requestPermissions(getActivity(),
new String[]{android.Manifest.permission.CAMERA}, RequestCameraPermissionID);
return;
}
try {
cameraSource.start(cameraView.getHolder());
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
cameraSource.stop();
}
});
barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
#Override
public void release() {
}
#Override
public void receiveDetections(Detector.Detections<Barcode> detections) {
final SparseArray<Barcode> qrcodes = detections.getDetectedItems();
if (qrcodes.size() != 0) {
textResult.post(new Runnable() {
#Override
public void run() {
//Create vibrate
Vibrator vibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(1000);
textResult.setText(qrcodes.valueAt(0).displayValue);
showResultDialogue(qrcodes.valueAt(0).displayValue);
}
});
}//End if Statement
}
});
Here is the onActivityResult and I think you dont have it.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
//We will get scan results here
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
//check for null
if (result != null) {
if (result.getContents() == null) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(getContext());
alertDialog.setTitle("Error");
alertDialog.setMessage("Scanning Error. Please try Again");
alertDialog.show();
} else {
//show dialogue with result
showResultDialogue(result.getContents());
}
} else {
// This is important, otherwise the result will not be passed to the fragment
super.onActivityResult(requestCode, resultCode, data);
}
}
//method to construct dialogue with scan results
public void showResultDialogue(final String result) {
final AlertDialog.Builder builder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder = new AlertDialog.Builder(getContext(), android.R.style.Theme_Material_Dialog_Alert);
} else {
builder = new AlertDialog.Builder(getContext());
}
//If the text of QR Code is success then Check-in Successful.
//if(result.equalsIgnoreCase("success")){
//Stop the scanner
barcodeDetector.release();
builder.setTitle("Successfully Scan QR Code")
.setMessage("Result ---> " + result)
.setPositiveButton("DONE", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(getContext(), MainActivity.class);
startActivity(intent);
//Click ok and Back to Main Page
}
}).create().show();
I'm new to Xamarin cross-platform app development, and I'm trying to implement on Android version of my app an external NFC tag reading.
When a tag is scanned, I would like my application to open and read the text inside the tag and finally perform some specific actions based on what was read.
I've this implementation on MainActivity.cs, but it doesn't work because it seems that I can't get the intent:
using Android.Content;
using System;
using System.Text;
using System.Diagnostics;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Xamarin.Forms;
using Android.Content.Res;
using FFImageLoading.Forms.Platform;
using Plugin.Permissions;
using Plugin.Permissions.Abstractions;
using Plugin.CurrentActivity;
using Android.Nfc;
using Android.Nfc.Tech;
using Poz1.NFCForms.Abstract;
using Poz1.NFCForms.Droid;
namespace Kibelis.Droid
{
[Activity(Label = "Kibelis", Icon = "#drawable/icon", Theme = "#style/MainTheme", LaunchMode = LaunchMode.SingleTop, MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
private NfcAdapter _nfcAdapter;
public object NFCUtil { get; private set; }
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
CachedImageRenderer.Init(true);
base.OnCreate(savedInstanceState);
CrossCurrentActivity.Current.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
_nfcAdapter = NfcAdapter.GetDefaultAdapter(this);
System.Diagnostics.Debug.WriteLine("CREATE");
// is attached.
LoadApplication(new App());
}
protected override void OnResume()
{
base.OnResume();
if (_nfcAdapter == null)
{
System.Diagnostics.Debug.WriteLine("NFC UNAVIABLE");
}
else
{
var tagDetected = new IntentFilter(NfcAdapter.ActionNdefDiscovered);
var filters = new[] { tagDetected };
var intent = new Intent(this, this.GetType()).AddFlags(ActivityFlags.SingleTop);
var pendingIntent = PendingIntent.GetActivity(this, 0, intent, 0);
_nfcAdapter.EnableForegroundDispatch(this, pendingIntent, filters, null);
System.Diagnostics.Debug.WriteLine("FOREGRAUND DISPATCH");
}
}
protected override void OnPause()
{
base.OnPause();
}
protected override void OnNewIntent(Intent intent)
{
base.OnNewIntent(intent);
System.Diagnostics.Debug.WriteLine("NEW INTENT");
if (intent.Extras.IsEmpty)
{
System.Diagnostics.Debug.WriteLine("empty");
}
else
{
System.Diagnostics.Debug.WriteLine("Not empty");
}
//For start reading
if (intent.Action == NfcAdapter.ActionTagDiscovered || intent.Action == NfcAdapter.ActionNdefDiscovered || intent.Action == NfcAdapter.ActionAdapterStateChanged
|| intent.Action == NfcAdapter.ActionTransactionDetected || intent.Action == NfcAdapter.ExtraNdefMessages || intent.Action == NfcAdapter.ExtraNdefMessages)
{
System.Diagnostics.Debug.WriteLine("DISCOVERD");
var tag = intent.GetParcelableExtra(NfcAdapter.ExtraTag) as Tag;
if (tag != null)
{
System.Diagnostics.Debug.WriteLine("TAG");
// First get all the NdefMessage
var rawMessages = intent.GetParcelableArrayExtra(NfcAdapter.ExtraNdefMessages);
if (rawMessages != null)
{
var msg = (NdefMessage)rawMessages[0];
System.Diagnostics.Debug.WriteLine("MESSAGE");
// Get NdefRecord which contains the actual data
var record = msg.GetRecords()[0];
if (record != null)
{
if (record.Tnf == NdefRecord.TnfWellKnown)
{
// Get the transfered data
var data = Encoding.ASCII.GetString(record.GetPayload());
System.Diagnostics.Debug.WriteLine("RECORD");
}
}
}
}
}
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults)
{
PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
Can you help me?
You are registering the foreground dispatch for the ActionNdefDiscovered intent. However, this intent filter also requires a specific data type (to be present on the tag and to be registered for the intent). If that's what you want, you need to add that data type (MIME type or URI) to the intent filter (variable tagDetected).
If, instead, you want to just listen for all tags, you want to use the ActionTagDiscovered intent instead. In fact, you can simply skip the intnent filter all together from the call to EnableForegroundDispatch:
_nfcAdapter.EnableForegroundDispatch(this, pendingIntent, null, null);
I would like to Start and Handle ZXing intent in non-Activity class. But I don't know how to catch Result in this class.
This code is typed in Xamarin, but it is not important.
ScannerZXing.cs:
Intent intenScanner;
public ScannerZXing()
{
intentScanner = ScanIntent.GetZXingScanIntent();
}
public override void Scan(Activity current)
{
//this.StartActivityForResult(this.intentScanner, 0); // error: Java.Lang.NullPointerExceptionn
//current.StartActivityForResult(this.intentScanner, 0); // OK, but I have to handle result in MainActivity (I don't want it.)
}
protected override void OnActivityResult(int requestCode, [Android.Runtime.GeneratedEnumAttribute()] Android.App.Result resultCode, Android.Content.Intent intent)
{
base.OnActivityResult(requestCode, resultCode, intent);
//....
}
MainClass.cs:
protected override void OnCreate(Bundle bundle)
{
//....
var scanner = new ScannerZXing();
Button btnScan = this.FindViewById<Button>(Resource.Id.btnScan);
btnScan.Click += delegate
{
scanner.Scan(this);
}
//....
}
If I do OnActivityResult in MainActivity, it works. But I want to move Scanning logic to separated class.
You could just get the nuget for zxing.
https://www.nuget.org/packages/ZXing.Net.Mobile
private async Task<string> Scan()
{
var scanner = new ZXing.Mobile.MobileBarcodeScanner() { BottomText = "Place red line on QR image to scan", TopText = "Place red line on QR image to scan", CancelButtonText = "Cancel scan", CameraUnsupportedMessage = "Camera not availabe on device" };
var scanResults = await scanner.Scan();
return scanresults;
}