I have been looking for an answer all over the internet.
The thing is, i found many ways to implement a QR code scanner in my app, in an activity.
This is one of the ways:
scan_btn = (Button) view.findViewById(R.id.scan_btn);
scan_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
IntentIntegrator integrator = new IntentIntegrator(getActivity());
integrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE_TYPES);
integrator.setPrompt("Scan!!");
integrator.setCameraId(0);
integrator.setBeepEnabled(false);
integrator.setBarcodeImageEnabled(false);
integrator.initiateScan();
}
});
Now i want to get it to work in a Fragment.
The problem is, it starts a new activity (the QR code reader)
Scans the QR code
But i dont get a response in my onActivityResult:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if (result != null) {
if (result.getContents() == null) {
System.out.println("Cancelled");
Toast.makeText(getActivity(), "You cancelled the scanning!", Toast.LENGTH_LONG).show();
} else {
System.out.println("Worked: " + result.getContents());
Toast.makeText(getActivity(), "scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
But what is going wrong?
I guess it has to do with this part:
IntentIntegrator integrator = new IntentIntegrator(getActivity());
It gets the activity, but it is a fragment, instead of an activity.
How can i solve this problem?
Communicating first to my Activity which holds the fragment and then get the result ?
Please help, Thanks :)
I will presume that the implementation of the onActivityResult is on your Fragment, right?
The IntentIntegrator implementation on your Fragment is right. So, just remove your onActivityResult code from the Fragment and put it on the Activity.
I had a similar problem and this was my solution.
IntentIntegrator intentIntegrator=
IntentIntegrator.forSupportFragment(FragmentNme.this);
It worked for me to solve my problem...rest all code is same.
Related
hi i am currently working on QR code scanner. I want to ask if it is possible to open another activity after the QR code have been scanned rather than getting it displayed as a toast?
below is my scanner file code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mtexthello=(TextView)findViewById(R.id.textview_hello);
scanbtn=(Button)findViewById(R.id.btn1) ;
final Activity activity=this;
scanbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
IntentIntegrator l=new IntentIntegrator(activity);
l.setDesiredBarcodeFormats(l.QR_CODE_TYPES);
l.setPrompt("scan");
l.setCameraId(0);
l.setBeepEnabled(false);
l.setBarcodeImageEnabled(false);
l.initiateScan();
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
IntentResult res= IntentIntegrator.parseActivityResult(requestCode, resultCode,data);
if(res!=null)
if(res.getContents()==null)
{
Toast.makeText(this,"u cancelled scanning",Toast.LENGTH_LONG).show();
}
else
{
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(intent);
// Toast.makeText(this,res.getContents(),Toast.LENGTH_LONG).show();
}
super.onActivityResult(requestCode, resultCode, data);
}
}
At a first reading it sounds as if the issue is how you're attempting to start the next activity, if not the activity itself.
Start a new app, and use a simple Button as the trigger for the new activity. Once you have the syntax and requirements correct there, apply what you've learned to the QR app.
If you're able to get the Toast to display from your existing code, then your difficulty has nothing to do with the QR code.
Maybe what you really need is to look at something like this (Start an Activity with a parameter) where you pass a parameter to the second activity.
I have two separate applications written using Xamarin.Android; for the sake of discussion, let's call them "Tristan" and "Isolde". Tristan has some state information that Isolde sometimes needs to know. Complication: Tristan may or may not be running at the moment Isolde develops the need to know his state.
I've got kludge working now where Isolde sends a special launch intent to Tristan, who then uses a broadcast intent to send information back to Isolde. (See my earlier question for details.)
"But wait!" I hear you cry, "Is this not a perfect use case for StartActivityForResult()?" Indeed it is! The code is a whole lot simpler, and everything I've read implies that this is how Android wants you to do stuff like this.
Unfortunately, I can't get it to work (despite trying many variations and reading the dozen-or-so related questions on this very site). My specific problem is that in Isolde's OnActivityResult() callback, the resultCode is always Result.Canceled and the data is always null.
Here is the code for Tristan (where commented-out bits represent variations I've tried):
using Android.App;
using Android.Content;
namespace com.example.Tristan.Android
{
[Activity(Name ="com.example.Tristan.Android.IsoldeQueryActivity")]
public class IsoldeQueryActivity : Activity
{
protected override void OnStart()
{
// base.OnStart();
var rtn = new Intent();
rtn.PutExtra("Test", "test");
//rtn.SetAction("TestAction");
SetResult(Result.Ok, rtn);
Finish();
//FinishActivity(1234);
}
}
}
And here is the relevant code from the Activity where Isolde needs to ask for Tristan's state:
private TaskCompletionSource<bool> TristanStateCompletion;
public async Task GetTristanState()
{
TristanStateCompletion = new TaskCompletionSource<bool>();
var req = new Intent("com.example.Tristan.Android.IsoldeQueryActivity");
//req.PutExtra(Intent.ExtraReturnResult, true);
StartActivityForResult(req, 1234);
var rtn = await TristanStateCompletion.Task;
if (!rtn) bomb("can't get state");
TristanStateCompletion = null;
}
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if(requestCode == 1234) {
DoStuffWith(data);
TristanStateCompletion?.TrySetResult(true);
}
}
Diagnostics -- or rather, a specific lack of them -- leads me to believe that Tristan's IsoldeQueryActivity.OnStart() is never actually being called.
Ideas, requests for additional information and/or useful experiments to try are all welcome. (If your idea is "Put <thing> in the manifest", remember this is Xamarin.Android and I have to do that by putting <relatedThing> in the attribute decorating the Activity.)
Edited to add: In Isolde's code, DoStuffWith(data) was crashing because data was null. When I changed that method to avoid that, I found that I got a (slightly later) exception thrown in StartActivityForResult():
Android.Content.ActivityNotFoundException No Activity found to handle Intent { act=com.example.Tristan.Android.IsoldeQueryActivity }
This leads me to believe I'm not creating the Intent properly in Isolde. Do I need to be using one of the other Intent constructors? If so, how specifically?
Okay, I think I have this figured out. The code in my original question had three major problems:
I was building the Intent incorrectly in Isolde.
I didn't export the IsoldeQueryActivity in Tristan.
The call to base.OnStart() in Tristan's OnStart override is mandatory.
Here is the working version of Tristan:
using Android.App;
using Android.Content;
namespace com.example.Tristan.Android
{
[Activity(Name ="com.example.Tristan.Android.IsoldeQueryActivity", Exported=true)]
public class IsoldeQueryActivity : Activity
{
protected override void OnStart()
{
base.OnStart();
var rtn = new Intent();
rtn.PutExtra("Test", "test");
SetResult(Result.Ok, rtn);
Finish();
}
}
}
And here is the fixed code from Isolde:
private TaskCompletionSource<bool> TristanStateCompletion;
public async Task GetTristanState()
{
TristanStateCompletion = new TaskCompletionSource<bool>();
var req = new Intent();
req.SetComponent(new ComponentName("com.example.Tristan.Android", "com.example.Tristan.Android.IsoldeQueryActivity"));
StartActivityForResult(req, 1234);
var rtn = await TristanStateCompletion.Task;
if (!rtn) bomb("can't get state");
TristanStateCompletion = null;
}
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if(requestCode == 1234) {
if(resultCode != Result.Ok) bomb("bad resultCode {0}", resultCode);
if(data == null) bomb("null data from Tristan");
DoStuffWith(data);
TristanStateCompletion?.TrySetResult(true);
}
}
I wanna write a native module for to scan barcode but it too hard for me to figure out a way to handle the result without adding a method to the MainActivity. It's not a good idea to modify the MainActivity such heavily because it's no easy job for application developers who writes javascript to use the module.
For example, if I use ZXing Android Embedded: https://github.com/journeyapps/zxing-android-embedded, I have to add a method to MainActivity to handle the result.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if(result != null) {
if(result.getContents() == null) {
Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
}
} else {
// This is important, otherwise the result will not be passed to the fragment
super.onActivityResult(requestCode, resultCode, data);
}
}
That makes an issue that any one who uses this module has to modify their MainActivity, which means the module is hard to use. So, any ideas to work it out?
You can just use react-native-rn-zxing:
npm i react-native-rn-zxing
then link it :
react-native link react-native-rn-zxing
And enjoy
I have implemented some of the zebra crossing (zxing) code in an attempt to create an Android application that scans some barcodes. Pretty basic stuff really. Here are the fundamentals of my code:
public void recognizeQRClick(View view) {
printingNewQR = false;
recognizingQR = true;
text1.setText("Recognize QR button clicked");
IntentIntegrator intentIntegrator = new IntentIntegrator(this);
intentIntegrator.initiateScan();
return;
}
#Override
public void onActivityResult (int requestCode, int resultCode, Intent intent) {
switch (requestCode) {
case IntentIntegrator.REQUEST_CODE:
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
if (scanResult != null) {
String contents = scanResult.getContents();
if(printingNewQR) {
return;
} else if(recognizingQR){
displayQRInfo(contents);
}
text1.setText(contents);
}
break;
}
}
The problem is that, while the scanning portion appears to work (when the appropriate button is clicked, the app jumps to the scanning screen, and when the barcode is centered a small golden dot appears in the center to indicate a good scan) it never finishes. The app just remains in the scanning screen, scanning the same barcode over and over. I have googled this problem extensively and found a similar issue in a couple of instances, but always their problems seem to be fixed once they use the IntentIntegrator class, which I am doing. What is wrong?
I am using following code to open Android Contacts
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnContacts = (Button) findViewById(R.id.btn_contacts);
txtContacts = (TextView) findViewById(R.id.txt_contacts);
btnContacts.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
txtContacts.setText("");
Intent intent = new Intent(Intent.ACTION_PICK, People.CONTENT_URI);
startActivityForResult(intent, PICK_CONTACT);
}
});
}
#Override
public void onActivityResult(int reqCode, int resultCode, Intent data) {
super.onActivityResult(reqCode, resultCode, data);
switch (reqCode) {
case (PICK_CONTACT):
if (resultCode == Activity.RESULT_OK) {
//display picked contact data.
}
}
}
Now I want to put Button at the top of this Contact activity when opened or add my own Menu in this Activity
Can any one guide me? Is this possible or not? If yes then please tell how to achieve this?
I don't believe that is possible as each Activity in Android is working on its own and by starting the Intent, you are basically giving the new Activity the focus (and control).
One way to do something like this would be to build a custom contact list activity that uses the public data providers to access the contacts and simply lists them then. Then you could add as many custom functions as you like or even add Intents for original actions (like viewing a contact's details).