intermittent QR Scan results using ZXing IntentIntegrator - android

I tried my best to find the solution before asking, however, I can't seem to locate a similar situation.
I've implemented a QR scanner for an app I am working on. I'm using the zxing library, specifically using the imports below. Also, the apps uses "Barcode Scanner" from play store (I was prompted to install).
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
The issue is that the scanner only works 1 out every 3-6 scans. I either get a null return, or no output. It always returns back to my source screen, and never produces an actual error.
I used this tutorial as a source: Android SDK: Create a Barcode Reader
Here is the relevant info from mainactivity:
public void onClick(View v){
//respond to clicks
if(v.getId()==R.id.scanQRButton){
//scan
IntentIntegrator scanIntegrator = new IntentIntegrator(this);
scanIntegrator.initiateScan();
formatTxt.setText( "Scan Initiated");
contentTxt.setText(" Scan Results: " + scanContent);
if(scanContent != null){
String userid,medname,tabstaken,dob;
StringTokenizer st = new StringTokenizer(scanContent, ",");
// token 0
dob = st.nextToken();
//token 1
medname = st.nextToken();
//token 2
tabstaken = st.nextToken();
//token 3
//rxnumber
DatabaseHandler db = new DatabaseHandler(getApplicationContext());
HashMap<String,String> user = new HashMap<String, String>();
user = db.getUserDetails();
//Store the userlog by passing to UserLogEntry
userid = user.get("uid");
//debug.setText("Userid: "+ userid+ " medname: " + medname + " tabs: " +tabstaken);
UserLogEntry userlog = new UserLogEntry(getApplicationContext(),userid,medname,tabstaken);
userlog.addUserLog();
}
}
}
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
//retrieve scan result
IntentResult scanningResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
if (scanningResult != null) {
//we have a result
scanContent = scanningResult.getContents();
}
else{
Toast toast = Toast.makeText(getApplicationContext(),
"No scan data received!", Toast.LENGTH_SHORT);
toast.show();
}
}
}
And here are the ZXing classes from the library package I'm using:
IntentResults:
https://code.google.com/p/zxing/source/browse/trunk/android-integration/src/com/google/zxing/integration/android/IntentResult.java?r=1273
IntentIntegrator:
https://code.google.com/p/zxing/source/browse/trunk/android-integration/src/com/google/zxing/integration/android/IntentIntegrator.java?spec=svn2260&r=2260
Any ideas on how to get this to work %100 of the time?
Thanks!

So I tried several different ways to get the scanner to work with zxing, and nothing would work. It just felt buggy no matter what I did. That on top of the fact that integrating the scanner so it doesn't need a third party app (as in Barcode scanner) was a major pain. I decided to look for an alternative and found ZBar.
If anyone has any problems using zxing for QR scanning I'd recommend using Zbar instead. The code itself is much simpler. You can use the example given on the zbar page and pretty much copy and paste it into your project without changes(or very little). Also, integrating it as an all inclusive scanner is simple as can be.
I'm including the instructions here for a more inclusive answer. This information is available in tutorials, and at the ZBar page, however, it doesn't hurt to include them here in my answer.
First download the zip here: https://github.com/dm77/ZBarScanner
Then add "ZBarScannerLibrary" as an existing android project.
For ZBarScannerLibrary: Right click->properties->android and check "Is Library"
Select your project (the one you're adding qr scanner to), right click->properties->android->Add select ZBarScannerLibrary.
Now add the ZBar code given on the page: https://github.com/dm77/ZBarScanner (shown below to be helpful.
Enjoy qr scanning without pulling out your hair
Here is the main activity for the sample provided with ZBar. Don't forget to add the appropriate lines to android manifest:
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera" />
Within the application element, add the activity declaration:
<activity android:name="com.dm.zbar.android.scanner.ZBarScannerActivity"
android:screenOrientation="landscape"
android:label="#string/app_name" />
I used a String Tokenizer to pull apart the QR results and sort them into specific variables.
package com.dm.zbar.android.examples;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Toast;
import com.dm.zbar.android.scanner.ZBarConstants;
import com.dm.zbar.android.scanner.ZBarScannerActivity;
import net.sourceforge.zbar.Symbol;
public class MainActivity extends Activity {
private static final int ZBAR_SCANNER_REQUEST = 0;
private static final int ZBAR_QR_SCANNER_REQUEST = 1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void launchScanner(View v) {
if (isCameraAvailable()) {
Intent intent = new Intent(this, ZBarScannerActivity.class);
startActivityForResult(intent, ZBAR_SCANNER_REQUEST);
} else {
Toast.makeText(this, "Rear Facing Camera Unavailable", Toast.LENGTH_SHORT).show();
}
}
public void launchQRScanner(View v) {
if (isCameraAvailable()) {
Intent intent = new Intent(this, ZBarScannerActivity.class);
intent.putExtra(ZBarConstants.SCAN_MODES, new int[]{Symbol.QRCODE});
startActivityForResult(intent, ZBAR_SCANNER_REQUEST);
} else {
Toast.makeText(this, "Rear Facing Camera Unavailable", Toast.LENGTH_SHORT).show();
}
}
public boolean isCameraAvailable() {
PackageManager pm = getPackageManager();
return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case ZBAR_SCANNER_REQUEST:
case ZBAR_QR_SCANNER_REQUEST:
if (resultCode == RESULT_OK) {
Toast.makeText(this, "Scan Result = " + data.getStringExtra(ZBarConstants.SCAN_RESULT), Toast.LENGTH_SHORT).show();
} else if(resultCode == RESULT_CANCELED && data != null) {
String error = data.getStringExtra(ZBarConstants.ERROR_INFO);
if(!TextUtils.isEmpty(error)) {
Toast.makeText(this, error, Toast.LENGTH_SHORT).show();
}
}
break;
}
}
}

Related

Android No Activity found to handle intent

I am basing my app off the foursquare-oAuth-sample app posted at Foursquare oAuth sample
Have made changes to MyActivity pretty much similar to the sample code but still getting this, can someone point out what I need to change, the code is as below
public class MyActivity extends FragmentActivity {
private static final int REQUEST_CODE_FSQ_CONNECT = 200;
private static final int REQUEST_CODE_FSQ_TOKEN_EXCHANGE = 201;
/**
* Obtain your client id and secret from:
* https://foursquare.com/developers/apps
*/
private static final String CLIENT_ID = "";
private static final String CLIENT_SECRET = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
ensureUi();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.my, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* Update the UI. If we already fetched a token, we'll just show a success
* message.
*/
private void ensureUi() {
boolean isAuthorized = !TextUtils.isEmpty(ExampleTokenStore.get().getToken());
TextView tvMessage = (TextView) findViewById(R.id.tvMessage);
tvMessage.setVisibility(isAuthorized ? View.VISIBLE : View.GONE);
Button btnLogin = (Button) findViewById(R.id.btnLogin);
btnLogin.setVisibility(isAuthorized ? View.GONE : View.VISIBLE);
btnLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Start the native auth flow.
Intent intent = FoursquareOAuth.getConnectIntent(MyActivity.this, CLIENT_ID);
// If the device does not have the Foursquare app installed, we'd
// get an intent back that would open the Play Store for download.
// Otherwise we start the auth flow.
if (FoursquareOAuth.isPlayStoreIntent(intent)) {
toastMessage(MyActivity.this, getString(R.string.app_not_installed_message));
startActivity(intent);
} else {
startActivityForResult(intent, REQUEST_CODE_FSQ_CONNECT);
}
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_FSQ_CONNECT:
onCompleteConnect(resultCode, data);
break;
case REQUEST_CODE_FSQ_TOKEN_EXCHANGE:
onCompleteTokenExchange(resultCode, data);
break;
default:
super.onActivityResult(requestCode, resultCode, data);
}
}
private void onCompleteConnect(int resultCode, Intent data) {
AuthCodeResponse codeResponse = FoursquareOAuth.getAuthCodeFromResult(resultCode, data);
Exception exception = codeResponse.getException();
if (exception == null) {
// Success.
String code = codeResponse.getCode();
performTokenExchange(code);
} else {
if (exception instanceof FoursquareCancelException) {
// Cancel.
toastMessage(this, "Canceled");
} else if (exception instanceof FoursquareDenyException) {
// Deny.
toastMessage(this, "Denied");
} else if (exception instanceof FoursquareOAuthException) {
// OAuth error.
String errorMessage = exception.getMessage();
String errorCode = ((FoursquareOAuthException) exception).getErrorCode();
toastMessage(this, errorMessage + " [" + errorCode + "]");
} else if (exception instanceof FoursquareUnsupportedVersionException) {
// Unsupported Fourquare app version on the device.
toastError(this, exception);
} else if (exception instanceof FoursquareInvalidRequestException) {
// Invalid request.
toastError(this, exception);
} else {
// Error.
toastError(this, exception);
}
}
}
private void onCompleteTokenExchange(int resultCode, Intent data) {
AccessTokenResponse tokenResponse = FoursquareOAuth.getTokenFromResult(resultCode, data);
Exception exception = tokenResponse.getException();
if (exception == null) {
String accessToken = tokenResponse.getAccessToken();
// Success.
toastMessage(this, "Access token: " + accessToken);
// Persist the token for later use. In this example, we save
// it to shared prefs.
ExampleTokenStore.get().setToken(accessToken);
// Refresh UI.
ensureUi();
} else {
if (exception instanceof FoursquareOAuthException) {
// OAuth error.
String errorMessage = ((FoursquareOAuthException) exception).getMessage();
String errorCode = ((FoursquareOAuthException) exception).getErrorCode();
toastMessage(this, errorMessage + " [" + errorCode + "]");
} else {
// Other exception type.
toastError(this, exception);
}
}
}
/**
* Exchange a code for an OAuth Token. Note that we do not recommend you
* do this in your app, rather do the exchange on your server. Added here
* for demo purposes.
*
* #param code
* The auth code returned from the native auth flow.
*/
private void performTokenExchange(String code) {
Intent intent = FoursquareOAuth.getTokenExchangeIntent(this, CLIENT_ID, CLIENT_SECRET, code);
startActivityForResult(intent, REQUEST_CODE_FSQ_TOKEN_EXCHANGE);
}
public static void toastMessage(Context context, String message) {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
}
public static void toastError(Context context, Throwable t) {
Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show();
}
Error Log
Here is the exception i am getting, can someone please point out why is it not able to find the activity to handle intent? Thank you
08-13 23:15:23.137 2754-2754/com.example.panaceatechnologysolutions.farhansfoursquareapp E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.panaceatechnologysolutions.farhansfoursquareapp, PID: 2754
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=market://details?id=com.example.panaceatechnologysolutions.farhansfoursquareapp&referrer=utm_source=foursquare-android-oauth&utm_term=CLIENT_ID }
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1691)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1482)
at android.app.Activity.startActivityForResult(Activity.java:3711)
at android.app.Activity.startActivityForResult(Activity.java:3669)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:840)
at android.app.Activity.startActivity(Activity.java:3914)
at android.app.Activity.startActivity(Activity.java:3882)
at com.example.panaceatechnologysolutions.farhansfoursquareapp.MyActivity$1.onClick(MyActivity.java:90)
at android.view.View.performClick(View.java:4598)
at android.view.View$PerformClick.run(View.java:19268)
at android.os.Handler.handleCallback(Handler.java:738)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5070)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:836)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:631)
08-13 23:15:30.157 2754-2765/com.example.panaceatechnologysolutions.farhansfoursquareapp I/art﹕ Heap transition to ProcessStateJankImperceptible took 7.253732ms saved at least 72KB
Ok so based on Rohans reply I checked, since I was doing this on the Emulator, this snippet from the Foursquare oAuth library I have in my project cannot create the intent based on the context and client Id. I am not sure why it returns null and as a result redirects me to the Google play store to install foursquare on my emulator. I have registered my app with foursquare and am using the registered client Id and the rest of the parameters used by this function are the ones in Foursquare oAuth Java class. If someone has worked with this library or can point out why it can't find the intent please let me know as I have been stuck on this for a couple of days.
This is the line of code like Rohan pointed out calling the Foursquare oAuth Java class in MyActivity class
Intent intent = FoursquareOAuth.getConnectIntent(MyActivity.this, CLIENT_ID);
And this is the getConnectIntent method in the Foursquare oAuth Java Class
public static Intent getConnectIntent(Context context, String clientId) {
Uri.Builder builder = new Uri.Builder();
builder.scheme(URI_SCHEME);
builder.authority(URI_AUTHORITY);
builder.appendQueryParameter(PARAM_CLIENT_ID, clientId);
builder.appendQueryParameter(PARAM_VERSION, String.valueOf(LIB_VERSION));
builder.appendQueryParameter(PARAM_SIGNATURE, getSignatureFingerprint(context));
Intent intent = new Intent(Intent.ACTION_VIEW, builder.build());
if (isIntentAvailable(context, intent)) {
return intent;
}
return getPlayStoreIntent(clientId);
}
it redirects you to play store becuase "isIntentAvailable is false" and it calls "getPlayStoreIntent" which redirects you to play store.
inside isIntentAvailable method
private static boolean isIntentAvailable(Context context, Intent intent) {
PackageManager packageManager = context.getPackageManager();
List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(
intent, PackageManager.MATCH_DEFAULT_ONLY);
return resolveInfo.size() > 0;
}
this method return true if a suitable package is found.
also check your client id is not null and is correct
Yes Rohan...you are right it is false because the intent wasnt returning anything from isIntentAvailable, but the real reason why that was not returning an intent back was because since I am using the emulator, the package manager is apparently looking for a foursquare.apk package installed which it didnt find. I didnt Foursquare anywhere indicate that their apk has to be installed which is not included as part of the oAuth Library which they provide in the link above on the sample project. I guess they assume you are using an Android device for testing and not the emulator. These are the steps to use oAuth from Foursquare on Android emulator from Android studio or Eclipse im guessing as well.
1) Download the Foursquare APK http://www.apk4fun.com/apk/6395/
2) As a pre-requisite open Android SDK Manager in Android studio and make sure Google API's are downloaded and installed, these are needed by Foursquare
3) copy the foursquare.apk file in the /Applications/sdk/platform-tools folder
4) install the apk using the adb tool in the folder like shown in this link How to install an apk on the emulator in Android Studio?
5) and now your app can use the emulator to contact foursquare and you will not be redirected to install the app on the emulator!
-Note, I noticed I had to reinstall the "foursquare.apk" when i closed down Android studio and the emulator the next day. But was easy since i knew what to do, Hopefully this saves someone else the frustration as it took me a couple of days to figure this out :)

Scanning Via IntentIntegrator never finishes

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?

Speech to text in emulator: No Activity found to handle Intent

I want to ask how I can use speech to text code on my emulator. My codes work on real device but not work on emulator. The error said :
No Activity found to handle Intent { act=android.speech.action.RECOGNIZE_SPEECH (has extras) }
What can I do?
package net.viralpatel.android.speechtotextdemo;
import java.util.ArrayList;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.view.Menu;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
protected static final int RESULT_SPEECH = 1;
private ImageButton btnSpeak;
private TextView txtText;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtText = (TextView) findViewById(R.id.txtText);
btnSpeak = (ImageButton) findViewById(R.id.btnSpeak);
btnSpeak.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(
RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "en-US");
try {
startActivityForResult(intent, RESULT_SPEECH);
txtText.setText("");
} catch (ActivityNotFoundException a) {
Toast t = Toast.makeText(getApplicationContext(),
"Ops! Your device doesn't support Speech to Text",
Toast.LENGTH_SHORT);
t.show();
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case RESULT_SPEECH: {
if (resultCode == RESULT_OK && null != data) {
ArrayList<String> text = data
.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
txtText.setText(text.get(0));
}
break;
}
}
}
}
You need to install onto your emulator an app that contains an Activity that handles the RECOGNIZE_SPEECH-intent. You might be able to find Google's VoiceSearch.apk on the web.
There are certain things you can't test using an emulator. Speech to text is on of them.
I'm not sure about this, but you can't use this android feature with the emulator.
No matter what, you should handle this exception with a try/ catch an give some feedback to the user.
You can check if there is that Activity in current device running your app doing something like:
PackageManager pm = context.getPackageManager();
List<ResolveInfo> infoList = pm.queryIntentActivities(new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);
if (infoList.size() == 0) {
/** Show some feedback to user if there is the activity. Something like "Your device is not abl to run this feature..."*/
}else{
/**Your current code goes here.*/
}
Let me know if it helps.
You need to install com.google.android.voicesearch application on target device which has no voice recognition activity like:
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.google.android.voicesearch"));
startActivity(browserIntent);
if you try to install Google's Search app - it won't help since it doesn't contain the VR engine inside and thus it will try to do the same - install com.google.android.voicesearch app but it could fail due to a bug in package name (pname:com.google.android.voicesearch instead of just pure package name). However com.google.android.voicesearch installation might be impossible due to "Not available in your country".
You might need a virtual SD Card. You can refer here

How to go back from calling intent

I call camera to take a picture. But I cannot go back to my own original activity after taking the picture. What's the problem? Thank you.
public void addEntry(View view)
{
String EntryName=RegisterName.toString();
Toast.makeText(this, EntryName, Toast.LENGTH_LONG);
Intent addEntryintent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File file = new File(getFilesDir(),EntryName);
registeryFileUri = Uri.fromFile(file);
addEntryintent.putExtra(MediaStore.EXTRA_OUTPUT, registeryFileUri);
startActivityForResult(addEntryintent,TAKE_PICTURE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == TAKE_PICTURE)
{
if (data != null)
{
Toast.makeText(this, "Successfully Registered!", Toast.LENGTH_LONG);
ImageView Registerimage= (ImageView)findViewById(R.id.RegisterPicture);
Registerimage.setImageURI(registeryFileUri);
}
}
}
It took me a while to get it working and I have made several things and finally it works. I can't tell certainly which of the things I did is the solution to the problem, but they all together form the working solution.
There are multiple reasons why the camera activity does not return back. Two major ones are:
path for the new picture is invalid, or non-existing, or it can't be created
application got suspended and saved path get lost.
So here is my code solving all these problems, all together working.
First I created helper class ImageServices:
class ImageServices {
private static String getTempDirectoryPath(Context ctx) {
File cache;
// SD Card Mounted
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
cache = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
"/Android/data/" + ctx.getPackageName() + "/cache/");
}
// Use internal storage
else {
cache = ctx.getCacheDir();
}
// Create the cache directory if it doesn't exist
if (!cache.exists()) {
cache.mkdirs();
}
return cache.getAbsolutePath();
}
public static Uri getOutputImageFileUri(Context ctx) {
// TODO: check the presence of SDCard
String tstamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File file = new File(getTempDirectoryPath(ctx), "IMG_" + tstamp + ".jpg");
return Uri.fromFile(file);
}
}
The code is partially inspired by developer.android.com and partially by CameraLauncher class of Apache Cordova project.
In my activity the event handler for button to take a picture looks like this:
private Uri imageFileUri;
private static final int MAKE_PHOTO_RESULT_CODE = 100;
private static final int PICK_PHOTO_RESULT_CODE = 101;
public void onMakePhoto(View v) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
imageFileUri = ImageServices.getOutputImageFileUri(this);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri);
Log.i("babies", "Taking picture: requested " + imageFileUri);
startActivityForResult(intent, MAKE_PHOTO_RESULT_CODE);
}
Method onActivityResult does not really contain much, as imageFileUri already points to the existing file and necessary rendering is done in onResume method, which is called when the activity gets back into foreground:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
switch(requestCode) {
case MAKE_PHOTO_RESULT_CODE:
assert imageFileUri != null;
break;
case ...
...other cases...
break;
}
}
}
But this is still not sufficient, as imageFileUri gets lost as your app gets suspended. And on regular device the chances are close to 100%. So next you need to store the value of imageFileUri to instance state:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (imageFileUri == null) {
outState.putString("file-uri", "");
}
else {
outState.putString("file-uri", imageFileUri.toString());
}
};
and load it again in - easiest is directly in onCreate:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (savedInstanceState != null) {
String fileUri = savedInstanceState.getString("file-uri");
if (!fileUri.equals("")) imageFileUri = Uri.parse(fileUri);
}
}
So, again, on top of many other solutions presented on this site as well as elsewhere, there are two major differences:
smarter getTempDirectoryPath inspired by Apache Cordova
allowing imageFileUri to survive suspended application
And now - at least for me - everything works fine.
Answer
Use appContext.getExternalCacheDir() and don't forget to mention permissons.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == TAKE_PICTURE)
{
if(resultCode==Activity.RESULT_OK)
{ //if (data != null)
//{
Toast.makeText(this, "Successfully Registered!", Toast.LENGTH_LONG);
ImageView Registerimage= (ImageView)findViewById(R.id.RegisterPicture);
Registerimage.setImageURI(registeryFileUri);
//}
}
else
Toast.makeText(this, "Not Registered!", Toast.LENGTH_LONG);
}
**"android.permission.CAMERA"**
Check whether the above permission is specified in your manifest or not
Note: It's better to use getExternalCacheDir() than getFilesDir() if you still dont get the
image then use that. Dont forgot to specify the permission "android.permission.WRITE_EXTERNAL_STORAGE" if you use the getExternalCacheDir().
On some devices data will unfortunately be null in onActivityResult after calling the camera activity. So you may need to save your state in your activity's variables, and them read them in onActivityResult. Be sure to save these variables in onSaveInstanceState and restore them in onCreate.

Android: how to Send the current time/date directly to the webserver when user click on the item

I created a listview with diff. activity to each items. When the user click on "clock in" I would like to grab the current time/date and send that data to the webserver in quickest way possible (without going through 2 step process to confirm). This will be for secondActivity class.
UPDATE* I am planning to add a password to the time/date within the phone so the user cant change them. I prefer current time/date within the phone instead of server time because if theres no signal/reception theres no way to clock in. How can I be able to grab the current time/date within the phone?
Customer.java
import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class Customer extends ListActivity
{
TextView selection;
String[] items = { "Start Trip", "Clock in", "Customer Svc",
"Independent Inspection", "Pick Up", "Log Out" };
#Override
public void onCreate(Bundle icicle)
{
super.onCreate(icicle);
setContentView(R.layout.main);
setListAdapter(new ArrayAdapter<String>(
this, android.R.layout.simple_list_item_1, items));
selection = (TextView) findViewById(R.id.selection);
}
private static final int ACTIVITY_0 = 0;
private static final int ACTIVITY_1 = 1;
private static final int ACTIVITY_2 = 2;
#Override
protected void onListItemClick(ListView l, View v, int position, long id)
{
super.onListItemClick(l, v, position, id);
final Intent intent = new Intent();
// Set up different intents based on the item clicked:
switch (position)
{
case ACTIVITY_0:
intent.setClass(this, com.company.merrill.IntentIntegrator.class);
break;
case ACTIVITY_1:
intent.setClass(this, com.company.merrill.SecondActivity.class);
break;
case ACTIVITY_2:
intent.setClass(this, com.company.merrill.ThirdActivity.class);
break;
default:
break;
}
// Pass the item position as the requestCode parameter, so on the `Activity`'s
// return you can examine it, and determine which activity were you in prior.
startActivityForResult(intent, position);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent)
{
super.onActivityResult(requestCode, resultCode, intent);
if (resultCode == RESULT_OK)
{
// Perform different actions based on from which activity is
// the application returning:
switch (requestCode)
{
case ACTIVITY_0:
// contents contains whatever the code was
String contents = intent.getStringExtra("SCAN_RESULT");
// Format contains the type of code i.e. UPC, EAN, QRCode etc...
String format = intent.getStringExtra("SCAN_RESULT_FORMAT");
// Handle successful scan. In this example
// I just put the results into the TextView
resultsTxt.setText(format + "\n" + contents);
break;
case ACTIVITY_1:
// TODO: handle the return of the SecondActivity
break;
case ACTIVITY_2:
// TODO: handle the return of the ThirdActivity
break;
default:
break;
}
}
else if (resultCode == RESULT_CANCELED)
{
// Handle cancel. If the user presses 'back'
// before a code is scanned.
resultsTxt.setText("Canceled");
}
}
the quickest way would be creating a new thread and opening a connection to the server.
Take a look to the code:
new Thread(new Runnable() {
public void run() {
URL url = new URL("http://www.example.com/?data="+System.currentTimeMillis());
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
//if there is no need to read the content then we close the connection
urlConnection.disconnect();
}
}).start();
Then on your server-side you've to read the $_GET['data'] variable if you're working with php.
Please consider that this solution is not ok for different timezones. I would probably rely on server-side date.
How about using Time:
Time timeToday = new Time();
timeToday.setToNow();
today = timeToday.year+"-"+ timeToday.MONTH+"-"+timeToday.monthDay;
Why rely on the time from a users device? What if I changed the time on my handset then clocked in? How are you going to handle different timezones?
Why not simply rely on server time of the webserver since you know you can depend on this and you're already making a call to the webserver?
use this to get current date and time:
private String getDateandTime() {
Calendar c = Calendar.getInstance();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formattedDate = df.format(c.getTime());
Log.e("Activity name", "time date "+formattedDate);
return formattedDate;
}
And call this function when user clicks to button and send this to server using networking library like Volley or Retrofit.

Categories

Resources