Stop mobile vision api after first detection - android

I'm trying to detect a QR code with the google mobile vision api.
The problem is that after detecting a QR code, the api calls continiously the "receiveDetections" function as long as the QR code is visible to the camera.
I need to stop after the first detection and send the result to my server to validate this code.
How can I stop the process after the first detection?
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.qrcode_scanner)
detector = BarcodeDetector.Builder(this).setBarcodeFormats(Barcode.ALL_FORMATS).build()
detector.setProcessor(object: Detector.Processor<Barcode> {
override fun release() {
override fun receiveDetections(detections: Detector.Detections<Barcode>?) {
val barcodes = detections?.detectedItems
if(barcodes!!.size()>0) {
Log.e("qrcode",barcodes.valueAt(0).displayValue)
sendQRCodeToServer(url,barcodes.valueAt(0).displayValue)
}
}
})
cameraSource = CameraSource.Builder(this,detector).setRequestedPreviewSize(1920,1080).setRequestedFps(25f).setAutoFocusEnabled(true).build()
svBarcode.holder.addCallback(object: SurfaceHolder.Callback2 {
override fun surfaceRedrawNeeded(holder: SurfaceHolder?) {
}
override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {
}
override fun surfaceDestroyed(holder: SurfaceHolder?) {
cameraSource.stop()
}
override fun surfaceCreated(holder: SurfaceHolder?) {
if(ContextCompat.checkSelfPermission(this#Scanner,
Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
cameraSource.start(holder)
startAnimation()
} else ActivityCompat.requestPermissions(this#Scanner, arrayOf(Manifest.permission.CAMERA),123)
}
})
}
}
override fun onDestroy() {
super.onDestroy()
detector.release()
cameraSource.stop()
cameraSource.release()
}

you can create function to stop camera,ex
private fun stopCamera(){
cameraSource.stop()
}
detector = BarcodeDetector.Builder(this).setBarcodeFormats(Barcode.ALL_FORMATS).build()
detector.setProcessor(object: Detector.Processor<Barcode> {
override fun release() {
override fun receiveDetections(detections: Detector.Detections<Barcode>?) {
val barcodes = detections?.detectedItems
if(barcodes!!.size()>0) {
Log.e("qrcode",barcodes.valueAt(0).displayValue)
sendQRCodeToServer(url,barcodes.valueAt(0).displayValue)
//add this to stop camera
stopCamera()
}
}
})
edit:
create variable for flag detection at first like
//to flag first detection
private var firstDetection=true
override fun onCreate(savedInstanceState: Bundle?) {
///.......
detector = BarcodeDetector.Builder(this).setBarcodeFormats(Barcode.ALL_FORMATS).build()
detector.setProcessor(object: Detector.Processor<Barcode> {
override fun release() {
}
override fun receiveDetections(detections: Detector.Detections<Barcode>?) {
val barcodes = detections?.detectedItems
//check firstDetection
if(barcodes!!.size()>0 && firstDetection) {
sendQRCodeToServer(url,barcodes.valueAt(0).displayValue)
//set firstDetection
firstDetection=false
}
}
})
}
}
hope this help....

Related

Can we do Speech Recognition and Video Capture in Android using camerax simultaneously?

I want to implement an app that can convert text to speech and record videos (with audio) simultaneously.
But when I am calling both function either one of them working (the recent one that has been called). Can anyone suggest some ways to implement these two together.
`
speechRecognizer = SpeechRecognizer.createSpeechRecognizer(activity)
val speechRecognizerIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
speechRecognizerIntent.putExtra(
RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM,
)
speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS,10000)
// speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS,30000)
speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault())
speechRecognizerIntent.putExtra("android.speech.extra.GET_AUDIO_FORMAT", "audio/MP3")
speechRecognizerIntent.putExtra("android.speech.extra.GET_AUDIO", true)
speechRecognizer.setRecognitionListener(object : RecognitionListener {
override fun onReadyForSpeech(bundle: Bundle?) {
speechRecognizer.startListening(speechRecognizerIntent)
}
override fun onBeginningOfSpeech() {}
override fun onRmsChanged(v: Float) {}
override fun onBufferReceived(bytes: ByteArray?) {}
override fun onEndOfSpeech() {
// changing the color of our mic icon to
// gray to indicate it is not listening
// #FF6D6A6A
}
override fun onError(i: Int) {}
override fun onResults(bundle: Bundle) {
}
override fun onPartialResults(bundle: Bundle) {
val result = bundle.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)
if (result != null) {
for (i in 0 until result.size){
text.add(result[0])
Log.d("Record",result[0])
//binding.tvtext.text = binding.tvtext.text.toString() + result[0]
}
}
}
override fun onEvent(i: Int, bundle: Bundle?) {}
})
speechRecognizer.startListening(speechRecognizerIntent)
}
`

How to Initiate virtual assistance with voice in android?

I am trying to build in app app voice assistant. I am able to record voice using SpeachRecognition but have to manually click button to start recording. How can I make it work by saying key word "Hey 'app name'" like hey google. I want my app to list the key word to start recording when app is in foreground.
fun initVoiceInput() {
val speechRecognizerIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
val speechRecognizer = SpeechRecognizer.createSpeechRecognizer(application)
speechRecognizerIntent.putExtra(
RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM
)
speechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault())
speechRecognizer.setRecognitionListener(object : RecognitionListener {
override fun onReadyForSpeech(bundle: Bundle) {
val data = bundle.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)
data?.apply {
// TODO
}
}
override fun onBeginningOfSpeech() {}
override fun onRmsChanged(v: Float) {}
override fun onBufferReceived(bytes: ByteArray) {}
override fun onPartialResults(p0: Bundle?) {
// TODO("Not yet implemented")
}
override fun onEvent(p0: Int, p1: Bundle?) {
// TODO("Not yet implemented")
}
override fun onEndOfSpeech() {
// TODO
}
override fun onError(p0: Int) {
// TODO("Not yet implemented")
}
override fun onResults(bundle: Bundle) {
val data = bundle.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)
data?.apply {
this.first()?.let {
if (it.contentEquals("my app name")) {
// Perform task here
}
}
}
}
})
}
It allows recording for service call but ends after few seconds. normally around 1 mins.

Android using Kotlin: New activity is not show showing anything, it's all blank?

I am trying to test myself in android development. For that I am trying to make a social media app with the help of firebase (using firebase authentication), but the problem is. After I login with every credentials correct, its is not showing the next activity screen which is meant to be opened. I don't know what mistake did I make. Here is the code for loginAcitivity screen:
class LoginActivity : AppCompatActivity() {
private val firebaseAuth = FirebaseAuth.getInstance()
private val firebaseAuthListener = FirebaseAuth.AuthStateListener {
val user = firebaseAuth.currentUser?.uid
user?.let {
startActivity(HomeActivity.newIntent(this))
finish()
}
}
#SuppressLint("ClickableViewAccessibility")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
setTextChangeListener(emailET, emailTIL)
setTextChangeListener(passwordET, passwordTIL)
loginProgressLayout.setOnTouchListener { v :View, event :MotionEvent -> true }
}
private fun setTextChangeListener(et: EditText, til: TextInputLayout) {
et.addTextChangedListener(object: TextWatcher{
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(s: Editable?) {
til.isErrorEnabled = false
}
})
}
fun onLogin(v: View){
var proceed = true
if(emailET.text.isNullOrEmpty()){
emailTIL.error = "Email is required"
emailTIL.isErrorEnabled = true
proceed = false
}
if(passwordET.text.isNullOrEmpty()){
passwordTIL.error ="Password is required"
passwordTIL.isErrorEnabled = true
proceed = false
}
if(proceed){
loginProgressLayout.visibility = View.VISIBLE
firebaseAuth.signInWithEmailAndPassword(emailET.text.toString(), passwordET.text.toString())
.addOnCompleteListener { task: Task<AuthResult> ->
if (!task.isSuccessful) {
loginProgressLayout.visibility = View.GONE
Toast.makeText(this#LoginActivity, "Login error: Either the username or password is wrong.", Toast.LENGTH_SHORT).show()
}
}.addOnFailureListener{e: Exception ->
e.printStackTrace()
loginProgressLayout.visibility = View.GONE
}
}
}
fun goToSignUp(v: View){
startActivity(SignUpActivity.newIntent(this))
finish()
}
override fun onStart() {
super.onStart()
firebaseAuth.addAuthStateListener { firebaseAuthListener }
}
override fun onStop() {
super.onStop()
firebaseAuth.removeAuthStateListener { firebaseAuthListener }
}
companion object{
fun newIntent(context: Context) = Intent(context, LoginActivity::class.java)
}
}
To test out that authentication is working or not I place a button in the activity to logout.
Help me please it's been week since I am stuck on it.
You were using lambda and in there you were no doing any task.
override fun onStart() {
super.onStart()
firebaseAuth.addAuthStateListener(firebaseAuthListener)
}
override fun onStop() {
super.onStop()
firebaseAuth.removeAuthStateListener(firebaseAuthListener)
}

How to zoom using gms.vision.CameraSource

I am using CameraSource to decode a barcode for my mobile app, everything is working perfectly but I would like to zoom the video from my camera.
I have been reading the documentation of CameraSource but i can't find anything about zooming.
I am wondering if anyone knows how to apply zoom using google play api CameraSource, if it's not possible I will do without it.
Here is my activity code :
cameraView = findViewById(R.id.surfaceView)
val detector = BarcodeDetector.Builder(applicationContext)
.setBarcodeFormats(Barcode.EAN_13 or Barcode.EAN_8 or Barcode.UPC_A or Barcode.UPC_E)
.build()
cameraSource = CameraSource.Builder(this, detector)
.setAutoFocusEnabled(true)
.build()
cameraView.holder.addCallback(object : SurfaceHolder.Callback {
override fun surfaceCreated(holder: SurfaceHolder) {
try {
cameraSource.start(surfaceView.holder)
} catch (ie: Exception) {
Log.e("CAMERA SOURCE", ie.message)
}
}
override fun surfaceChanged(
holder: SurfaceHolder,
format: Int,
width: Int,
height: Int
) {
}
override fun surfaceDestroyed(holder: SurfaceHolder) {
cameraSource.stop()
}
})
detector.setProcessor(object : Detector.Processor<Barcode> {
override fun release() {}
override fun receiveDetections(detections: Detections<Barcode>) {
val barcodes = detections.detectedItems
if (barcodes.size() != 0) {
detector.release()
val resultIntent = Intent(this#BarcodeActivity, AddFoodActivity::class.java)
resultIntent.putExtra("EXTRA_BARCODE", barcodes.valueAt(0).rawValue)
startActivity(resultIntent)
finish()
}
}
})

Socket connection in background

I need to make an application where, while the user is authorized, it keeps the socket connection until it is logged out. For this purpose, a foreground service is created, which starts after the authorization of the user, and stops when it is logged out. It implements connection and reconnection on the socket.
All works well until you press the power button and turn off the charging. After this, the user stops receiving pongs from the server and the SocketTimeoutException is received on the OkHttp, and also stops receiving messages on the socket. On JavaWebsocket, The connection was closed because the other endpoint did not respond with a pong in time is received, after which you can successfully create a new socket connection, but it will repeat the same problem in the loop.
In the settings, the optimization of the battery for this application was disabled. What can I do to make a stable connection socket work in the background?
Implementation of activity:
class MainActivity : BaseFragmentPermissionActivity(), MainMvpView {
private var mIsSocketBound = false
private var mSocketBroadcastReceiver = SocketBroadcastReceiver(this)
private var mSocketConnection = SocketConnection(this)
private var mSocketService: SocketService? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
doBindService()
}
private fun doBindService() {
bindService(Intent(this, SocketService::class.java), mSocketConnection, Context.BIND_AUTO_CREATE)
mIsSocketBound = true
}
override fun onStart() {
super.onStart()
...
mSocketService?.doStopForeground()
}
override fun onStop() {
mSocketService?.doStartForeground()
...
super.onStop()
}
override fun onDestroy() {
doUnbindService()
...
super.onDestroy()
}
private fun doUnbindService() {
if (mIsSocketBound) {
unbindService(mSocketConnection)
mIsSocketBound = false
mSocketService = null
}
}
class SocketConnection(mainActivity: MainActivity) : ServiceConnection {
private val mMainActivity: WeakReference<MainActivity> = WeakReference(mainActivity)
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
val socketService = (service as SocketService.LocalBinder).getService()
mMainActivity.get()?.mSocketService = socketService
if (socketService.isForeground()) {
socketService.doStopForeground()
}
}
override fun onServiceDisconnected(name: ComponentName?) {
mMainActivity.get()?.mSocketService = null
}
}
}
Implementation of service:
class SocketService : Service(), MvpErrorHandler {
private val mConnectingHandler = Handler()
private val mConnectingTask = ConnectingTask(this)
private var mIsRunningForeground = false
override fun onBind(intent: Intent?): IBinder {
startService(Intent(this, SocketService::class.java))
return mBinder
}
override fun onCreate() {
super.onCreate()
DaggerServiceComponent.builder()
.serviceModule(ServiceModule(this))
.applicationComponent(PatrolApplication.applicationComponent)
.build()
.inject(this)
startConnecting()
...
}
override fun onDestroy() {
...
stopConnecting()
super.onDestroy()
}
private fun startConnecting() {
if (!mIsConnecting) {
mIsConnecting = true
mConnectingHandler.post(mConnectingTask)
}
}
private fun stopConnecting() {
mConnectingHandler.removeCallbacks(mConnectingTask)
mIsConnecting = false
}
private fun openConnection() {
mCompositeDisposable.add(mDataManager.getSocketToken()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(false, this, {
stopConnecting()
mDataManager.openSocketConnection(it.token)
}, {
mConnectingHandler.postDelayed(mConnectingTask, RECONNECT_TIME.toLong())
return#subscribe ErrorHandlerUtil.handleGetSocketError(it, this)
}))
}
class ConnectingTask(socketService: SocketService) : Runnable {
private val mSocketService: WeakReference<SocketService> = WeakReference(socketService)
override fun run() {
mSocketService.get()?.openConnection()
}
}
}
Implementation of SocketHelper using JavaWebsocket:
class CustomApiSocketHelper #Inject constructor() : ApiSocketHelper {
private var mCustomSocketClient: WebSocketClient? = null
override fun openSocketConnection(token: String) {
mCustomSocketClient = CustomSocketClient(URI(CONNECTION_URL + token))
mCustomSocketClient?.connect()
}
override fun sendMessage(text: String) {
if (mCustomSocketClient?.isOpen == true) {
try {
mCustomSocketClient?.send(text)
} catch (t: Throwable) {
Log.e(TAG, Log.getStackTraceString(t))
Crashlytics.logException(t)
}
}
}
override fun closeSocketConnection() {
mCustomSocketClient?.close(CLOSE_REASON_OK)
}
class CustomSocketClient(uri: URI) : WebSocketClient(uri) {
init {
connectionLostTimeout = PING_TIMEOUT
}
override fun onOpen(handshakedata: ServerHandshake?) {
sendBroadcast(SocketActionType.OPEN.action)
}
override fun onMessage(message: String?) {
sendBroadcast(SocketActionType.MESSAGE.action, message)
}
override fun onClose(code: Int, reason: String?, remote: Boolean) {
if (code != CLOSE_REASON_OK) {
//call startConnecting() in service
sendBroadcast(SocketActionType.CLOSE.action)
}
}
override fun onError(ex: Exception?) {
sendBroadcast(SocketActionType.FAILURE.action)
}
private fun sendBroadcast(type: Int) {
val intent = Intent().apply { action = SOCKET_BROADCAST_ACTION }
intent.putExtra(SOCKET_MESSAGE_TYPE, type)
LocalBroadcastManager.getInstance(CustomApplication.application).sendBroadcast(intent)
}
private fun sendBroadcast(type: Int, text: String?) {
val intent = Intent().apply { action = SOCKET_BROADCAST_ACTION }
intent.putExtra(SOCKET_MESSAGE_TYPE, type)
intent.putExtra(SOCKET_MESSAGE, text)
LocalBroadcastManager.getInstance(CustomApplication.application).sendBroadcast(intent)
}
}
}
Implementation of SocketHelper using OkHttp:
class CustomApiSocketHelper #Inject constructor() : ApiSocketHelper {
private var mCustomSocketClient: WebSocket? = null
override fun openSocketConnection(token: String) {
val request = Request.Builder()
.url(CONNECTION_URL + token)
.build()
mCustomSocketClient = CustomApplication.applicationComponent.authorizedClient().newWebSocket(request, CustomSocketClient())
}
override fun sendMessage(text: String) {
mPatrolSocketClient?.send(text)
}
override fun closeSocketConnection() {
mCustomSocketClient?.close(CLOSE_REASON_OK, null)
}
class CustomSocketClient : WebSocketListener() {
override fun onOpen(webSocket: WebSocket, response: Response) {
super.onOpen(webSocket, response)
sendBroadcast(SocketActionType.OPEN.action)
}
override fun onMessage(webSocket: WebSocket, text: String) {
super.onMessage(webSocket, text)
sendBroadcast(SocketActionType.MESSAGE.action, text)
}
override fun onClosed(webSocket: WebSocket?, code: Int, reason: String?) {
super.onClosed(webSocket, code, reason)
if (code != CLOSE_REASON_OK) {
sendBroadcast(SocketActionType.CLOSE.action)
}
}
override fun onFailure(webSocket: WebSocket?, t: Throwable?, response: Response?) {
super.onFailure(webSocket, t, response)
sendBroadcast(SocketActionType.FAILURE.action)
}
private fun sendBroadcast(type: Int) {
val intent = Intent().apply { action = SOCKET_BROADCAST_ACTION }
intent.putExtra(SOCKET_MESSAGE_TYPE, type)
LocalBroadcastManager.getInstance(CustomApplication.application).sendBroadcast(intent)
}
private fun sendBroadcast(type: Int, text: String?) {
val intent = Intent().apply { action = SOCKET_BROADCAST_ACTION }
intent.putExtra(SOCKET_MESSAGE_TYPE, type)
intent.putExtra(SOCKET_MESSAGE, text)
LocalBroadcastManager.getInstance(CustomApplication.application).sendBroadcast(intent)
}
}
}
...
#Provides
#Singleton
#Named(AUTHORIZED_CLIENT)
fun provideAuthorizedClient(builder: OkHttpClient.Builder, interceptor: Interceptor, authenticator: Authenticator): OkHttpClient = builder
.addInterceptor(interceptor)
.authenticator(authenticator)
.pingInterval(PING_TIMEOUT.toLong(), TimeUnit.SECONDS)
.build()
#Provides
#Singleton
fun provideOkHttpBuilder() = CustomApiHelper.getOkHttpBuilder()
fun getOkHttpBuilder(): OkHttpClient.Builder {
val builder = OkHttpClient.Builder()
builder.readTimeout(NETWORK_CALL_TIMEOUT, TimeUnit.SECONDS)
builder.writeTimeout(NETWORK_CALL_TIMEOUT, TimeUnit.SECONDS)
if (BuildConfig.DEBUG) {
val logger = HttpLoggingInterceptor()
logger.level = HttpLoggingInterceptor.Level.BASIC
builder.addInterceptor(logger)
}
return builder
}
After some research and testing on different devices, it was found that for stable operation on the network, it is necessary that the device is charging or has a screen enabled. In the other case, neither PARTIAL_WAKE_LOCK nor the disabling of battery optimization in the settings itself can solve the problem.
The recommended way to solve this problem is to add this code to your activity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
This prevents the screen from turning off and provides a stable socket connection. But we still have the situation that the user can press the power button. And, if at this moment the device is charging, everything will work as before, but otherwise, we will get the socket disconnect. To solve this problem, you need to periodically wake the device, in order to support the ping-pong process. This is not a recommended solution because it will lead to battery draining, and can not guarantee 100% performance, but if this moment is critical for you, then you can use this solution. You need to add this code, in a suitable place for you, in this example is used at the time of ping.
#Suppress("DEPRECATION")
override fun onWebsocketPing(conn: WebSocket?, f: Framedata?) {
if (mSocketWakeLock == null) {
mSocketWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK or PowerManager.SCREEN_BRIGHT_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP, TAG)
}
mSocketWakeLock?.takeIf { !it.isHeld }?.run { acquire(WAKE_TIMEOUT) }
super.onWebsocketPing(conn, f)
mSocketWakeLock?.takeIf { it.isHeld }?.run { release() }
}
Using this solution, on the test devices socket connection, with good Internet, stays stable for 2 hours or more. Without it, it is constantly disconnect.

Categories

Resources