Android camera works for one time only after giving permission - java

I try to show the content of the built-in camera inside my android device using ArCore. I have handled a code for asking permission at the beginning of the application. If I provide the permission I can see the current image stream coming from the camera.
After relaunching the application the result is black. The only solution is to revoke the camera permission inside the setting. Then the application asks again for permission and shows the image stream on the screen.
Is anybody who face the same problem? Do I have to refresh the permission? If I do RequestCameraPermission(); without checking permission, the activity is paused and resumed in a cycle. But I can see the first frame.
In the console the following error appears:
D/ACameraDevice: Device error received, code 3, frame number 51, request ID 0, subseq ID 0
and android_camera.cc:1088 Camera capture failed! frame: 51 reason: 1.
Code 3 is ERROR_CAMERA_DISABLED depending on https://github.com/aosp-mirror/platform_development/blob/master/ndk/platforms/android-24/include/camera/NdkCameraDevice.h
After some time only
I/native: analytics_logger.cc:190 The AnalyticsClient.sendAnalyticsMessage() method returned false. Will retry...
E/native: analytics_logger.cc:198 Could not send event. Event will be dropped.
is called in a loop. There is no activity anymore.
My code:
public class GameActivity extends NativeActivity
{
static GameActivity s_Instance;
public static GameActivity GetInstance()
{
return s_Instance;
}
#Override
public void onCreate(Bundle _SavedInstanceState)
{
super.onCreate(_SavedInstanceState);
s_Instance = this;
nativeInitializeInterface(getApplicationContext());
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onResume()
{
super.onResume();
if (!HasCameraPermission())
{
RequestCameraPermission();
return;
}
RequestCameraPermission();
}
#Override
protected void onPause()
{
super.onPause();
}
#Override
public void onStop()
{
super.onStop();
}
#Override
public void onDestroy()
{
super.onDestroy();
}
#Override
public void onRequestPermissionsResult(int _RequestCode, String[] _Permissions, int[] _Results)
{
if (!HasCameraPermission())
{
Toast.makeText(this, "Camera permission is needed to run this application", Toast.LENGTH_LONG).show();
if (!ShouldShowRequestPermissionRationale())
{
// Permission denied with checking "Do not ask again".
LaunchPermissionSettings();
}
finish();
}
}
public int GetDeviceOrientation()
{
return getResources().getConfiguration().orientation;
}
public int GetDeviceRotation()
{
return getWindowManager().getDefaultDisplay().getRotation();
}
public int GetDeviceDimensionWidth()
{
Point Size = new Point();
getWindowManager().getDefaultDisplay().getSize(Size);
return Size.x;
}
public int GetDeviceDimensionHeight()
{
Point Size = new Point();
getWindowManager().getDefaultDisplay().getSize(Size);
return Size.y;
}
public boolean HasCameraPermission()
{
return this.checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
}
public void RequestCameraPermission()
{
this.requestPermissions(new String[] {Manifest.permission.CAMERA}, 0);
}
public boolean ShouldShowRequestPermissionRationale()
{
return this.shouldShowRequestPermissionRationale(Manifest.permission.CAMERA);
}
public void LaunchPermissionSettings()
{
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", this.getPackageName(), null));
this.startActivity(intent);
}
public native void nativeInitializeInterface(Context context);
static
{
System.loadLibrary("app_droid");
}
}

Where exactly do you have the logic for presenting the image on screen? Maybe you only have it inside the permission granted callback.
(I'd put this answer as a comment, but can't yet due to reputation)

Related

java.lang.illegalStateException when getting mediaPlayer.getCurrentPosition and SeekBar going to Intial on Pause

I'm getting java.lang.IllegalStateException in my Android Music Player Application every time when I closes the Activity
mCurrentPosition = mediaPlayer.getCurrentPosition()/1000; // In milliseconds
I've tried nearly all the codes available and even all at java.lang.illegalStateException randomly occurs when getting mediaPlayer.getCurrentPosition also
Here's my Java code where I'm using it:
protected void initializeSeekBar(){
mSeekBar.setMax(mediaPlayer.getDuration()/1000);
mRunnable = new Runnable() {
#Override
public void run() {
int mCurrentPosition;
if(mediaPlayer!=null && mediaPlayer.isPlaying()){
mCurrentPosition = mediaPlayer.getCurrentPosition()/1000; // In milliseconds
}
else {
mCurrentPosition = 0;
}
if (mSeekBar != null) {
mSeekBar.setProgress(mCurrentPosition);
getAudioStats();
}
handler.postDelayed(mRunnable,1000);
}
};
handler.postDelayed(mRunnable,1000);
}
Please Help me out of this. Thanks in Advance
Edit 1
Also, my Seekbar goes to start when the music pauses and on play, it continues from where it was before pausing
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
getAudioStats();
initializeSeekBar();
if(mediaPlayer != null && fromUser) {
mediaPlayer.seekTo(progress * 1000);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
protected void getAudioStats(){
long duration = mediaPlayer.getDuration()/1000; // In milliseconds
long due = (mediaPlayer.getDuration() - mediaPlayer.getCurrentPosition())/1000;
long pass = duration - due;
String test = DateUtils.formatElapsedTime(pass);
String test1 = DateUtils.formatElapsedTime(due);
current_time.setText("" + test);
//mDuration.setText("" + duration + " seconds");
total_time.setText("" + test1);
}
You need to remove your runnable from the handler queue when the activity closes (or, better yet, when it pauses). Try putting this in your activity's onPause() method:
handler.removeCallbacks(mRunnable);
For additional robustness, inside the runnable itself, you should only re-queue the runnable if the activity is still active. So instead of this:
handler.postDelayed(mRunnable,1000);
you should do this (assuming this code is in the activity class):
if (!isDestroyed()) {
handler.postDelayed(mRunnable,1000);
}
Also make sure you are stopping the media player before the activity is destroyed.
P.S. If you call initializeSeekBar() multiple times, you will be reassigning mRunnable and leaving the old one in the handler queue where it can cause trouble later. To fix this, you should add this at the start of initializeSeekBar():
protected void initializeSeekBar(){
if (mRunnable != null) {
handler.removeCallbacks(mRunnable);
}
// ... the rest of the method that you currently have

Animated Vector drawable animation not working properly

I want to run AnimatedVectorDrawable animation on infinite loop.
final AnimatedVectorDrawableCompat avd = AnimatedVectorDrawableCompat.create(this, R.drawable.avd_anim_happy);
mImageView.setImageDrawable(avd);
// animation on infinite loop
avd.registerAnimationCallback(new Animatable2Compat.AnimationCallback() {
#Override
public void onAnimationStart(Drawable drawable) {
super.onAnimationStart(drawable);
Log.e(TAG, "onAnimationStart() called");
}
#Override
public void onAnimationEnd(Drawable drawable) {
Log.e(TAG, "onAnimationEnd() called");
avd.start();
}
});
avd.start();
}
This works fine when I tested with Nougat device. But when I try to run this on KitKat device, callback is called but animation is not started again. There is no
"onAnimationStart() called" log message. But upon doing the following.
#Override
public void onAnimationEnd(Drawable drawable) {
Log.e(TAG, "onAnimationEnd() called");
if (avd.isRunning()) {
Log.e(TAG, "avd running!!");
avd.stop();
}
avd.start();
}
onAnimationEnd() and onAnimationStart() are getting called again and again. But for some reason animation just stopped after playing for one time.
I was having the same issue with old platforms, turns out i work around it by posting the start after the end event.
imageView.post(new Runnable() {
#Override
public void run() {
avd.start();
}
});

UtteranceProgressListener won't call the functions

I am trying to make a speech powered app, however I have run into a major problem.
My UtteranceProgressListener Class will not call any of the given methods regardless of where I place the Speak method.
Here is my code:
This is my OnCreate Method:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
voiceBtn = (Button) findViewById(R.id.startListeningBtn);
voiceBtn.setEnabled(false);
textToSpeech = new TextToSpeech(mContext,new botListener());
}
This is the OnInitListner Imeplementation
public class botListener implements TextToSpeech.OnInitListener{
#Override
public void onInit(int i) {
if(i == TextToSpeech.SUCCESS)
{
int s = textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
#Override
public void onStart(String s) {
Toast.makeText(getApplicationContext(),"Done Speaking",Toast.LENGTH_SHORT).show();
}
#Override
public void onDone(String s) {
Toast.makeText(getApplicationContext(),s,Toast.LENGTH_SHORT).show();
}
#Override
public void onError(String s) {
Toast.makeText(getApplicationContext(),"Done Speaking",Toast.LENGTH_SHORT).show();
}
});
Log.d(TAG,String.valueOf(s));
int result = textToSpeech.setLanguage(Locale.ENGLISH);
if(result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED){
Log.e(TAG,"Language not supported");
Intent installLanguage = new Intent(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installLanguage);
}
Log.d(TAG,"Started Voice Speaker");
}
else{
Log.e(TAG,"initialization failed");
}
}
}
Now, when I press the button, the event that fires is:
public void initVoiceRecog(View v){
//Toast.makeText(mContext,"Clicked",Toast.LENGTH_SHORT).show();
Speak("hello","1");
// does some other things here after that
}
private void Speak(String text,String identifierID){
if(Build.VERSION.SDK_INT>21) {
Bundle params = new Bundle();
params.putString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,identifierID);
textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, params, identifierID);
}
else{
// ttsMap is a HashMap
ttsMap.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,identifierID);
textToSpeech.speak(text,TextToSpeech.QUEUE_FLUSH,ttsMap );
}
}
My Question is, after saying hello, it does not fire the OnStart() or the OnError() or the OnDone() methods. Why is this happening?
I tried with the deprecated setOnUtteranceListner() as well, same result. It does not fire any of the methods, the Toasts don't show up.
Please tell a fix or a workaround for this.
The Devices I tried on are:
API 19 Micromax Canvas Nitro
API 21 Samsung S4
API 23(Marshmellow) ASUS Zenfone
I finally figured out why the callbacks were not working. Turns out, they were working and calling on a separate thread. So to execute the normal functionality, call the functions in the 'Activity.this.RunOnUiThread' and put this in the call back fuctions.

How to pause game when user turn off screen

I have problem with one of my games. This is time based puzzle game and I have problem with it. When user press on/off button on Android device game doesn`t stop, but timer goes on and on till game over. When user turn on screen again, he can see game over screen. But I want to make scenario when user press on/off button game will pause.
Any suggestions? I`m pretty new in programming so please explain me very basic method to do this.
Thanks all!
Edit. Timer code
private void initializeProgressBar() {
//initialize progressbar
progress = ApplicationConstants.GAME_TIME;
mProgress = (ProgressBarDetermininate) findViewById(R.id.progressDeterminate);
mProgress.setMax(progress);
mProgress.setProgress(progress );
timer = new Timer();
progressBarUpdateTask = new ProgressBarUpdateTask();
timer.schedule(progressBarUpdateTask, 20, 20);
}
class ProgressBarUpdateTask extends TimerTask {
#Override
public void run() {
runOnUiThread(new Runnable(){
#Override
public void run() {
progress-=1;
if(progress==0)
{
TimeOver();
}
mProgress.setProgress(progress);
}
});
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
this.timer.cancel();
}
Pause your game in onStop() or onPause() (depending on your need) in the Activity context your game is running in.
I am assuming you are using android's activity...
#Override
protected void onResume() {
super.onResume();
// Resume the timer or show a button for the user to press when ready
// !!! Also check if timer exits because onResume is called before onCreate!!!
}
#Override
protected void onPause() {
super.onPause();
// Pause the timer
}
When you press screen off or Power button onPause method of the application will be called and when you again press Power button, applications onResume method will be called, you should pause timer in onPause and resume it in onResume.
One way to do this is to detect the user presence, here's an example
At beginning of your game start the LockService
startService(new Intent(getApplicationContext(), LockService.class));
LockService.java
public class LockService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);
final BroadcastReceiver mReceiver = new ScreenReceiver();
registerReceiver(mReceiver, filter);
return super.onStartCommand(intent, flags, startId);
}
public class LocalBinder extends Binder {
LockService getService() {
return LockService.this;
}
}
}
Then finally the BroadcastReceiver where you can stop your game.
ScreenReceiver.java
public class ScreenReceiver extends BroadcastReceiver {
public static boolean wasScreenOn = true;
#Override
public void onReceive(final Context context, final Intent intent) {
Log.e("LOB","onReceive");
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
// do whatever you need to do here
wasScreenOn = false;
/* PAUSE THE GAME HERE*/
Log.e("LOB","wasScreenOn"+wasScreenOn);
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
// and do whatever you need to do here
wasScreenOn = true;
}else if(intent.getAction().equals(Intent.ACTION_USER_PRESENT)){
}
}
}
As correctly mentioned in other answers, you can also use the onPause() method
#Override
protected void onPause() {
super.onPause();
// stop the game
}

ending android activity from surfaceview using thread.join

I'm working on my first app for android - snake. Right now I'm trying to implement 'game over' for that app. So basically when the snake hits the wall, app should ask your name and put it witch your score on HiScore. Well i'm stuk on hitting the wall fragment. Im experimenting with threads and so far I've found no way to stop it without getting errors.
I googled a lot, and everyone is saying that thread.join(); is waiting for thread to end, so how long does it take to end the thread that is drawing simple squares once per half second? When im hitting the back button on my phone while playing, pause(); function works perfectly. Log "game has ended" appears on LogCat.
So the problem is that i cant stop this activity when snake hits the wall, Log "game has ended" never occurs. Why is that?
My code:
public class SnakeCage extends SurfaceView implements Runnable{
// blah blah .. functions that draw and stuff ..
public void pause() {
isRunning = false;
while(true){
try {
aThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
aThread = null;
Log.d("pause()","game has ended"); // <<<<<<<<<THIS ONE>>>>>>>>>
}
public void resume() {
isRunning = true;
aThread = new Thread(this);
aThread.start();
}
public void init(){
// blah blah...
}
private void gameOver() {
int pHeadX = snakeHead.posX;
int pHeadY = snakeHead.posY;
Log.d("gameOver()", "checking");
if(pHeadY<0 || pHeadX<0 || pHeadX>23 || pHeadY>19){
Log.d("gameOver()", "game now will end");
gameOver = true;
}
}
public void run() {
while (isRunning){
if(!aHolder.getSurface().isValid())
continue;
canvas = aHolder.lockCanvas();
// drawing
gameOver();
if(gameOver) break;
// more drawing
aHolder.unlockCanvasAndPost(canvas);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(gameOver){
pause();
}
}
and the activity class:
public class PlayingActivity extends Activity implements OnClickListener{
SnakeCage v;
Button snakeGoUp;
Button snakeGoDown;
Button snakeGoLeft;
Button snakeGoRight;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.frame_layout);
v = (SnakeCage)findViewById(R.id.sView);
// listeners and stuff
}
#Override
protected void onPause() {
super.onPause();
v.pause();
}
#Override
protected void onResume() {
super.onResume();
v.resume();
}
#Override
public void onClick(View view) {
switch(view.getId()){
case R.id.snakeUp:
v.move(1);
break;
case R.id.snakeDown:
v.move(2);
break;
case R.id.snakeLeft:
v.move(3);
break;
case R.id.snakeRight:
v.move(4);
break;
}
}
}
i just did:
Context context = getContext();
((PlayingActivity)context).finish();
from:
How can I end an activity from inside a SurfaceView class or nested thread
although it does not satisfy me... its enough for now
I would suggest using a LocalBroadcastManager to send a message to the Activity, to notify it to kill itself. You can have an inner class in the Activity to receive the broadcast and call a private method in the Activity which will end it.
public class MyActivity extends Activity {
public void onCreate(Bundle state) {
LocalBroadcastManager.getInstance(this).registerReceiver(new MessageHandler(),
new IntentFilter("kill"));
}
private void killActivity() {
finish();
}
public class MessageHandler extends BroadcastReceiver {
onReceive(Context context, Intent intent) {
killActivity();
}
}
Then in your SurfaceView all you need to do is:
Intent intent = new Intent("kill");
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);
Its a little more code but its a lot cleaner IMHO.

Categories