I'm currently having problems with Google vision. There is nothing wrong with the library actually, its works great. All what I'm trying to accomplish now is set a rectangular area where the CameraSource will focus only on. The aim is try to capture text within that particular rectangular box only. I've tried many examples on StackOverflow but they all didn't seem to work. My current working code with the Google Vision ( 11.8.0 ) is
cameraView = findViewById(R.id.surfaceview);
output = findViewById(R.id.output);
TextRecognizer textRecognizer = new TextRecognizer.Builder(ScanVoucher.this).build();
if(!textRecognizer.isOperational()) {
show_alert("Text Recognition not supported on this device");
} else {
cameraSource = new CameraSource.Builder(ScanVoucher.this, textRecognizer)
.setAutoFocusEnabled(true)
.setFacing(CameraSource.CAMERA_FACING_BACK)
.setRequestedFps(2.0f)
.setRequestedPreviewSize(300, 300)
.build();
cameraView.getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
try {
cameraSource.start(cameraView.getHolder());
} catch (IOException e) {
show_alert("Unable to access camera");
} catch (SecurityException e) {
finish();
} catch(Exception e) {
//Kill
finish();
}
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
cameraSource.stop();
}
});
textRecognizer.setProcessor(new Detector.Processor<TextBlock>() {
#Override
public void release() {
}
#Override
public void receiveDetections(Detector.Detections<TextBlock> detections) {
final SparseArray<TextBlock> items = detections.getDetectedItems();
if(items.size() != 0) {
output.post(new Runnable() {
#Override
public void run() {
StringBuilder builder = new StringBuilder();
for(int i = 0; i < items.size(); i++) {
TextBlock item = items.valueAt(i);
builder.append(item.getValue());
}
try {
output.setText(builder.toString());
} catch (Exception e) {
output.setText(e.getMessage());
}
}
});
}
}
});
}
As I said, everything works great. Wondering how I could set the rectangular box like preview area so that the camera only captures text with the box just like the QR or bar code scanner apps. Thanks in advance.
Please dont abandon project.. You can Reset your .setRequestedPreviewSize(80, 24) to fit.
for me, this only captures the first text line. i hope you see this
Related
I'm working on a project right now, no one has been able to solve this error. It only happens on some real devices.
I'm trying to capture bluetooth signals in a dialog. I force bluetooth to be turned on before the dialog opens, I force it to get location information and androidManifest permissions are all there. It works correctly on almost all of the phones used in the project, but in a few of them, the bluetooth scan falls into the onScanFailed method as soon as it starts. It is included as errorCode 2 in onScanFailed. I couldn't find the solution, can you help me?
scan method
private void scanForBeacon(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
btAdapter = BluetoothAdapter.getDefaultAdapter();
mLEScanner = btAdapter.getBluetoothLeScanner();
if (btAdapter != null){
if(btAdapter.isEnabled()){
beaconList = new ArrayList<BeaconItem>();
peripheralList = new ArrayList<String>();
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
switch(state) {
case BluetoothAdapter.STATE_OFF:
break;
case BluetoothAdapter.STATE_TURNING_OFF:
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
Log.d(TAG, "bluetooth adapter try to enable");
btAdapter.getDefaultAdapter().enable();
}}, 500);
break;
case BluetoothAdapter.STATE_ON:
mLEScanner = btAdapter.getBluetoothLeScanner();
mLEScanner.startScan(filters, settings, mScanCallback);
break;
case BluetoothAdapter.STATE_TURNING_ON:
break;
}
}
}
};
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
getOwnActivity().registerReceiver(receiver, filter);
settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build();
filters = new ArrayList<>();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
beaconList.clear();
peripheralList.clear();
btAdapter.startLeScan(leScanCallback);
} else {
try{
beaconList.clear();
peripheralList.clear();
mLEScanner = btAdapter.getBluetoothLeScanner();
mLEScanner.startScan(filters, settings, mScanCallback);
}catch (Exception e) {
Log.e("hata", e.getMessage());
}
}
} else{
getOwnActivity().runOnUiThread(new Runnable() {
public void run() {
Global.showAlert(getOwnActivity(), SweetAlertDialog.ERROR_TYPE, R.string.error, R.string.must_enabled_bt_for_join_attendance, R.string.ok, new SweetAlertDialog.OnSweetClickListener() {
#Override
public void onClick(SweetAlertDialog sweetAlertDialog) {
dismiss();
if(timer != null)
timer.cancel();
}
});
}
});
}
}
}
}
onScanFailed
#Override
public void onScanFailed(final int errorCode) {
try{
if (tryTime == 0){
mLEScanner.stopScan(mScanCallback);
btAdapter.getDefaultAdapter().disable();
tryTime++;
} else{
getOwnActivity().runOnUiThread(new Runnable() {
public void run() {
Global.closeLoadingView();
Global.showAlert(getOwnActivity(), SweetAlertDialog.ERROR_TYPE, getString(R.string.error), getString(R.string.cbn_scan_failed).replace("[error_code]", String.valueOf(errorCode)));
}
});
}
} catch (Exception e){
try{
getOwnActivity().runOnUiThread(new Runnable() {
public void run() {
Global.closeLoadingView();
Global.showAlert(getOwnActivity(), SweetAlertDialog.ERROR_TYPE, getString(R.string.error), getString(R.string.cbn_scan_failed).replace("[error_code]", String.valueOf(errorCode)));
}
});
} catch (Exception x){
x.printStackTrace();
}
}
}
I forced bluetooth and location information to be turned on before the dialog opens.
Some devices with problems
Samsung A7 2017
Tecno spark 5 pro kd7 -> android version 10
Xiaomi redmi note 9s
I am currently trying to implement computer vision algorithms on my android device. My idea is to have a camera preview running and draw on top of the preview (in a separate view)
edges and other geometric figures. To command the camera, I use the camera2 API.
I start a capture session with two requests with the following targets:
Request number 1: target/surface -> an ImageReader for image processing
Request number 2: target/surface -> a SurfaceView for camera preview
I burst both requests with setRepeatingBurst. Now a problem occurs when I process the image in the
ImageReader callback (onImageAvailable). When I process for let's say 500 ms then the image preview drops to 1 fps. I think the problem is because the image.close() gets delayed and that the second request is somehow connected to that image.
I thought that if I have two requests then there are sent two individual images to each surface. But apparently that's not the case. Well, I could make a quick copy in the ImageReader callback and close the image afterwards. And then start processing the copy. But the thing is that I don't
want to copy.
Here is the code:
HandlerThread imageProcessingThread = new HandlerThread("imageProcessingThread");
imageProcessingThread.start();
Handler imageProcessingHandler = new Handler(imageProcessingThread.getLooper());
ImageReader imageReader = ImageReader.newInstance(width, height, format, 1);
imageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireNextImage();
if(image == null) return;
// simulating processing
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
// processing end
image.close();
}
}, imageProcessingHandler);
try {
HandlerThread imageProcessingThread3 = new HandlerThread("imageProcessingThread3");
imageProcessingThread3.start();
Handler imageProcessingHandler3 = new Handler(imageProcessingThread3.getLooper());
camManager.openCamera(cam.second, new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice cameraDevice) {
try {
List<Surface> surfaces = new ArrayList<>();
surfaces.add(binding.svPreview.getHolder().getSurface());
surfaces.add(imageReader.getSurface());
cameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession session) {
try {
CaptureRequest.Builder requestBuilder1 = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
requestBuilder1.addTarget(imageReader.getSurface());
requestBuilder1.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, new Range<>(30, 30));
CaptureRequest.Builder requestBuilder2 = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
requestBuilder2.addTarget(binding.svPreview.getHolder().getSurface());
requestBuilder2.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, new Range<>(30, 30));
HandlerThread imageProcessingThread2 = new HandlerThread("imageProcessingThread2");
imageProcessingThread2.start();
Handler imageProcessingHandler2 = new Handler(imageProcessingThread2.getLooper());
List<CaptureRequest> requests = new ArrayList<>();
requests.add(requestBuilder1.build());
requests.add(requestBuilder2.build());
session.setRepeatingBurst(requests, new CameraCaptureSession.CaptureCallback() {
#Override
public void onCaptureProgressed(#NonNull CameraCaptureSession session, #NonNull CaptureRequest request, #NonNull CaptureResult partialResult) {
}
#Override
public void onCaptureCompleted(#NonNull CameraCaptureSession session, #NonNull CaptureRequest request, #NonNull TotalCaptureResult result) {
}
}, imageProcessingHandler2);
} catch (Exception ex) {
fatalError(ex.getMessage());
return;
}
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
fatalError("onConfigureFailed");
return;
}
}, null);
} catch (Exception ex) {
fatalError(ex.getMessage());
return;
}
}
#Override
public void onDisconnected(#NonNull CameraDevice cameraDevice) {
}
#Override
public void onError(#NonNull CameraDevice cameraDevice, int i) {
}
}, imageProcessingHandler3);
} catch (Exception ex) {
fatalError(ex.getMessage());
return;
}
As you can see in the pictures, toast line is working properly but process function not working another activity.
This code line does not workking on background, only work on Activity.
Process p = Runtime.getRuntime().exec("input touchscreen tap 500 500");
My purpose is touch the different screen, EX:WhatsApp or any app.
btndene.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new Thread(new Runnable() {
#Override
public void run() {
Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.teamviewer.quicksupport.market");
startActivity(launchIntent);
for(int i = 0; i<10; i++) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
update(i);
}
}
private void update(final int i) {
runOnUiThread(new Runnable() {
#Override
public void run() {
//txt.setText("Hello"+i);
// komut = "input keyevent 30";
//calistir(komut);
Toast.makeText(MainActivity.this,"Bastin",Toast.LENGTH_SHORT).show();
try {
p = Runtime.getRuntime().exec("input touchscreen tap 500 500");
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}).start();
Due to security reasons it wont work on other apps...You can use any UI automation frameworks like Robotium,Expresso to do this..
Try using monkeyrunner instead. It works with any app.
I use libGDX tools and BaseGameUtils.GameHelper in my project.
Every thing looks perfect and all functional works good.
Sign In, Sign out, Achievements, Leaderboards everything work normally.
Except "Welcome Back <Name>" popups that didn't show up when I start my game.
As I said, all functional works fine. My game automatically start sign in when game started.
But when I force sign out and sign in again.
In sign in flow process will bring up the Google Play Services green dialog prompt user to sign in.
After I clicked in Sign In, My game took time a while to connect to server and show Welcome Back popup.
In this section the popup appear to my game. I'm so very confusing why it works.
I test many time with my real device.
I notice that Welcome Back popup don't show if you didn't enter Google Play Services diglog before. I think it maybe some wrong configuration or my miss-understanding.
I try to use setViewForPopups but it didn't work.
I want to setup ViewForPopups before GoogleApiClient connected.
But there are a lot of error when I use this way.
The last thing, it's not only happen with Welcome Back popup.
It also a achievements popup when I achieve something.
Here my part of code :
package com.huskybear.polyknock.android;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.view.View;
import android.widget.Toast;
import com.badlogic.gdx.Gdx;
import com.google.android.gms.games.Games;
import com.google.android.gms.games.GamesActivityResultCodes;
import com.google.example.games.basegameutils.GameHelper;
import com.huskybear.polyknock.Core.IGoogleServices;
public class AndroidGGServicesHelper implements IGoogleServices {
private final static int RC_SIGN_IN = 9001;
private final static int RC_LEADER_BOARDS = 9002;
private final static int RC_ACHIEVEMENTS = 9003;
private GameHelper Helper;
private Activity mActivity;
private Context mContext;
private Runnable callback = null;
private View popups;
private boolean isSignIn = false;
private boolean isStartAutoFlow = false;
public AndroidGGServicesHelper(Activity act, View popups) {
this.mActivity = act;
this.mContext = act.getApplicationContext();
this.popups = popups;
Helper = new GameHelper(act, GameHelper.CLIENT_GAMES | GameHelper.CLIENT_PLUS);
GameHelper.GameHelperListener helperListener = new GameHelper.GameHelperListener() {
#Override
public void onSignInFailed() {
if (isStartAutoFlow) {
Toast("Unable to sign in.", Toast.LENGTH_SHORT);
if (callback != null) {
callback.run();
}
}
}
#Override
public void onSignInSucceeded() {
isSignIn = true;
if (callback != null) {
callback.run();
}
}
};
Helper.setConnectOnStart(false);
Helper.setMaxAutoSignInAttempts(0);
Helper.setup(helperListener);
}
#Override
public void signIn(final boolean isAutoFlow) {
try {
mActivity.runOnUiThread(new Runnable() {
public void run() {
if (isAutoFlow) {
isStartAutoFlow = true;
Helper.reconnectClient();
} else {
Helper.beginUserInitiatedSignIn();
}
}
});
} catch (Exception e) {
Gdx.app.log("MainActivity", "Log in failed: " + e.getMessage() + ".");
}
}
#Override
public void signOut() {
try {
mActivity.runOnUiThread(new Runnable() {
//#Override
public void run() {
Helper.signOut();
isSignIn = false;
Toast("Sign out complete.", Toast.LENGTH_SHORT);
if (callback != null) {
callback.run();
}
}
});
} catch (Exception e) {
Gdx.app.log("MainActivity", "Log out failed: " + e.getMessage() + ".");
}
}
#Override
public void achievementUnlock(String type) {
try {
Games.Achievements.unlock(Helper.getApiClient(), type);
} catch (Exception e) {
}
}
#Override
public void submitScore(int type, long score) {
}
#Override
public void rateGame() {
Games.setViewForPopups(Helper.getApiClient(), popups);
}
#Override
public void showLeaderboards() {
try {
if (isConnected()) {
mActivity.startActivityForResult(
Games.Leaderboards.getAllLeaderboardsIntent(Helper.getApiClient()),
RC_LEADER_BOARDS
);
} else {
signIn(false);
}
} catch (Exception e) {
Helper.reconnectClient();
}
}
#Override
public void showAchievements() {
try {
if (isConnected()) {
mActivity.startActivityForResult(
Games.Achievements.getAchievementsIntent(Helper.getApiClient()),
RC_ACHIEVEMENTS
);
} else {
signIn(false);
}
} catch (Exception e) {
Helper.reconnectClient();
}
}
#Override
public void onStart() {
try {
Helper.onStart(mActivity);
} catch (Exception e) {
}
}
#Override
public void onStop() {
Helper.onStop();
}
#Override
public void disconnect() {
Helper.disconnect();
isSignIn = false;
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (((requestCode == RC_LEADER_BOARDS) || (requestCode == RC_ACHIEVEMENTS))
&& resultCode == GamesActivityResultCodes.RESULT_RECONNECT_REQUIRED) {
Helper.disconnect();
isSignIn = false;
if (callback != null) {
callback.run();
}
} else {
Helper.onActivityResult(requestCode, resultCode, data);
}
}
public boolean isConnected() {
return Helper.isSignedIn();
}
#Override
public boolean isSignIn() {
return isSignIn;
}
#Override
public void Toast(final String text, final int length) {
try {
mActivity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(mContext, text, length).show();
}
});
} catch (Exception e) {
}
}
#Override
public void setCallback(Runnable run) {
callback = run;
}
}
Sorry for my bad language.
I am trying to make a Helicopter-like game (as you can probably tell, I'm using "Rocket Man" instead of a helicopter). I'm new to Android programming and to Stack Overflow, so don't pick apart my code too much (please). Anyway, right now I'm just trying to get the rocketman to move up while touch is held down, and move down while touch is released.
It isn't working out very well.
I'm using a Moto XT886 for testing, (in case that's relevent). When I run the application, it starts up and loads the MainActivity perfectly well. When I touch the screen the first time (boolean start == true), the text views are hidden, as they are supposed to. However, on the second, third, fourth and all the rest of the times I touch the screen (Start == false), nothing happens. There are no errors in Log Cat, the code doesn't seem to recognize the touch.
I'm pretty sure that it has something to do with those while loops, but I'm using this application mainly to learn Android Java and I don't know enough (yet) to recognize that I'm doing something wrong. Are you able to put a while loop with the conditions as the MotionEvent of an onTouchListner? Or is it something else?
Either way, I appreciate the help, this is an awesome website (this is the first question I couldn't find already asked on Stack Overflow, and for all I know, mine could've already been answered)!
Here's the code to my MainActivity, if you need the .xml code as well, (though I'm pretty sure that's unnecessary) just say the word.
public class MainActivity extends ActionBarActivity {
boolean Start;
RelativeLayout rLayout;
TextView gameTitle;
TextView clickStart;
TextView highScore;
Handler handler;
ImageView rocketMan;
float Y;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initialize();
rLayout.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (Start == true) {
gameTitle.setVisibility(View.GONE);
clickStart.setVisibility(View.GONE);
highScore.setVisibility(View.GONE);
Start = false;
}
if (Start = false) {
while (event.getAction() == MotionEvent.ACTION_DOWN) {
Y = -7;
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
Thread.sleep(100);
handler.post(new Runnable() {
#Override
public void run() {
HeliMove();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
while (event.getAction() != MotionEvent.ACTION_DOWN) {
Y = 7;
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
Thread.sleep(100);
handler.post(new Runnable() {
#Override
public void run() {
HeliMove();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
return true;
}
});
}
private void initialize() {
rLayout = (RelativeLayout) findViewById(R.id.mainlayout);
Start = true;
gameTitle = (TextView) findViewById(R.id.rocketmanTitle);
clickStart = (TextView) findViewById(R.id.tapToStart);
highScore = (TextView) findViewById(R.id.highScore);
handler = new Handler();
rocketMan = (ImageView) findViewById(R.id.rocketMan);
}
private void HeliMove() {
rocketMan.setY(rocketMan.getY() + Y);
}
}
Thanks a million!