Android IllegalArgumentException lockCanvas() - java

I've been struggling with this exception and I've looked around but there's nothing to help me.
Here's the code
package com.example.surfacetest;
import android.app.Activity;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class BoardSurfaceActivity extends Activity {
/** Called when the activity is first created. */
private static final String TAG = BoardSurfaceActivity.class.getSimpleName();
private BoardSurface bS;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bS = new BoardSurface(this);
setContentView(bS);
Log.d(TAG, "View added");
}
#Override
protected void onDestroy() {
Log.d(TAG, "Destroying...");
super.onDestroy();
}
#Override
protected void onStop() {
Log.d(TAG, "Stopping...");
super.onStop();
}
#Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
}
#Override
protected void onPause() {
Log.d(TAG, "Pausing...");
super.onPause();
}
#Override
protected void onResume() {
Log.d(TAG, "Resuming...");
super.onResume();
}
public class BoardSurface extends SurfaceView implements SurfaceHolder.Callback, Runnable {
final String TAG = BoardSurface.class.getSimpleName();
private Stuff stuff;
Thread t = null;
SurfaceHolder holder;
boolean isItOk = false;
public BoardSurface(Context context) {
super(context);
holder = getHolder();
getHolder().addCallback(this);
stuff = new Stuff(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher), 50, 50);
t = new Thread(this);
setFocusable(true);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG, "Surface created");
resume();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(TAG, "Surface Destroyed");
pause();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// delegating event handling to the droid
stuff.handleActionDown((int) event.getX(), (int) event.getY());
// check if in the lower part of the screen we exit
if (event.getY() > getHeight() - 50) {
((Activity) getContext()).finish();
} else {
Log.d(TAG, "Coords: x=" + event.getX() + ",y=" + event.getY());
}
}
if (event.getAction() == MotionEvent.ACTION_MOVE) {
// the gestures
if (stuff.isTouched()) {
// the droid was picked up and is being dragged
stuff.setX((int) event.getX());
stuff.setY((int) event.getY());
}
}
if (event.getAction() == MotionEvent.ACTION_UP) {
// touch was released
if (stuff.isTouched()) {
stuff.setTouched(false);
}
}
return true;
}
public void draw(Canvas canvas) {
canvas.drawColor(Color.BLUE);
stuff.draw(canvas);
}
#Override
public void run() {
while (isItOk) {
holder = getHolder();
if (holder.getSurface().isValid()) {
Canvas c = null;
try {
// make sure holder is updated
c = holder.lockCanvas(null);
if (c != null) {
synchronized (holder) {
draw(c);
}
}
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (c != null) {
holder.unlockCanvasAndPost(c);
}
}
}
}
}
public void pause() {
isItOk = false;
while (true) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
t = null;
}
public void resume() {
if (t.getState() == Thread.State.TERMINATED) {
t = new Thread(this);
isItOk = true;
t.start();
} else {
isItOk = true;
t.start();
}
}
}
}
What is super strange is that I have this trace :
10-22 08:54:41.153: D/BoardSurface(17298): Surface created
10-22 08:54:41.394: E/memalloc(17298): /dev/pmem: Failed to map buffer size:24641536 offset:23699456 fd:56 Error: Invalid argument
10-22 08:54:41.394: E/gralloc(17298): Could not mmap handle 0x89e2b8, fd=56 (Invalid argument)
10-22 08:54:41.394: E/gralloc(17298): gralloc_register_buffer: gralloc_map failed
10-22 08:54:41.394: W/GraphicBufferMapper(17298): registerBuffer(0x89e2b8) failed -22 (Invalid argument)
10-22 08:54:41.394: E/GraphicBuffer(17298): unflatten: registerBuffer failed: Invalid argument (-22)
10-22 08:54:41.394: E/memalloc(17298): /dev/pmem: Failed to map buffer size:24641536 offset:23699456 fd:56 Error: Invalid argument
10-22 08:54:41.394: E/gralloc(17298): Could not mmap handle 0x89e2b8, fd=56 (Invalid argument)
10-22 08:54:41.394: E/libgenlock(17298): perform_lock_unlock_operation: GENLOCK_IOC_DREADLOCK failed (lockType0x1,err=Bad file number fd=56)
10-22 08:54:41.394: E/gralloc(17298): gralloc_lock: genlock_lock_buffer (lockType=0x2) failed
10-22 08:54:41.394: W/GraphicBufferMapper(17298): lock(...) failed -22 (Invalid argument)
10-22 08:54:41.394: W/Surface(17298): failed locking buffer (handle = 0x89e2b8)
10-22 08:54:41.424: E/SurfaceHolder(17298): Exception locking surface
10-22 08:54:41.424: E/SurfaceHolder(17298): java.lang.IllegalArgumentException
10-22 08:54:41.424: E/SurfaceHolder(17298): at android.view.Surface.nativeLockCanvas(Native Method)
10-22 08:54:41.424: E/SurfaceHolder(17298): at android.view.Surface.lockCanvas(Surface.java:236)
10-22 08:54:41.424: E/SurfaceHolder(17298): at android.view.SurfaceView$4.internalLockCanvas(SurfaceView.java:807)
10-22 08:54:41.424: E/SurfaceHolder(17298): at android.view.SurfaceView$4.lockCanvas(SurfaceView.java:787)
10-22 08:54:41.424: E/SurfaceHolder(17298): at com.example.surfacetest.BoardSurfaceActivity$BoardSurface.run(BoardSurfaceActivity.java:137)
10-22 08:54:41.424: E/SurfaceHolder(17298): at java.lang.Thread.run(Thread.java:841)
in my running loop.
But here's the tricky part ! When I press back (not HOME) then start the app from the menu again. It just simply works.
So I really don't know what I'm missing.
Additional info : I'm running on a HTC Sensation XE, CM 10.2 (Android 4.3.1)
EDIT:
The device is not the issue here. Tried with another HTC on stock ROM.
EDIT 2 :
Even though I check :
if (holder.getSurface().isValid())
Which is specifically saying that lockcanvas() will succeed if it is true, I get this exception
10-22 10:11:27.688: E/SurfaceHolder(22195): Exception locking surface
10-22 10:11:27.688: E/SurfaceHolder(22195): java.lang.IllegalArgumentException
10-22 10:11:27.688: E/SurfaceHolder(22195): at android.view.Surface.nativeLockCanvas(Native Method)
10-22 10:11:27.688: E/SurfaceHolder(22195): at android.view.Surface.lockCanvas(Surface.java:236)
10-22 10:11:27.688: E/SurfaceHolder(22195): at android.view.SurfaceView$4.internalLockCanvas(SurfaceView.java:807)
10-22 10:11:27.688: E/SurfaceHolder(22195): at android.view.SurfaceView$4.lockCanvas(SurfaceView.java:787)
10-22 10:11:27.688: E/SurfaceHolder(22195): at com.example.surfacetest.BoardSurfaceActivity$BoardSurface.run(BoardSurfaceActivity.java:144)
10-22 10:11:27.688: E/SurfaceHolder(22195): at java.lang.Thread.run(Thread.java:841)
EDIT 3 :
Works on Galaxy S4 Stock ROM and Emulator Intelx86 4.2.2

#CinetiK: Post the rest of your stacktrace.
HTC devices are notorious when it comes to rotation and surface tests. Have you tried this:
Restart your phone.
Go to Safe mode (i.e. restart the phone and when you see the HTC logo, long press Volume down button). The phone will restart again and go into Safe mode.
Once phone is in Safe mode, go to Settings | Display & Gestures | G-Sensor Calibration. Then, calibrate your phone while ensuring your phone rests on a flat surface. Once calibration is successfully completed, restart the phone in normal mode.
If the above steps still do not fix the error, and since you're using CM 10.2, I would recommend testing your Android app on stock ROMs first. While I have nothing against custom Android ROMs (I used them myself), from experience I have had more unexplained errors on custom ROMs than stock ROMs. Try a stock ROM first and see if you still get the same error.

Related

java.lang.RuntimeException: An error occurred while executing doInBackground()

I am programming an Android app and on two devices my app crashes with the following Problem:
Update: There seems to be a problem, which was about the mediarecorder. Now I get a slightly different problem:
FATAL EXCEPTION: AsyncTask #3
Process: online.simpledesign.bikelog, PID: 14660
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:353)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
at java.util.concurrent.FutureTask.run(FutureTask.java:271)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:203)
at android.os.Handler.<init>(Handler.java:117)
at android.app.Dialog.<init>(Dialog.java:123)
at android.app.Dialog.<init>(Dialog.java:168)
at android.support.v7.app.AppCompatDialog.<init>(AppCompatDialog.java:46)
at android.support.v7.app.AlertDialog.<init>(AlertDialog.java:97)
at android.support.v7.app.AlertDialog$Builder.create(AlertDialog.java:980)
at online.simpledesign.bikelog.Record$MediaPrepareTask.doInBackground(Record.java:539)
at online.simpledesign.bikelog.Record$MediaPrepareTask.doInBackground(Record.java:524)
at android.os.AsyncTask$2.call(AsyncTask.java:333)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
... 4 more
The Code that is executed when the error occurs is:
class MediaPrepareTask extends AsyncTask<Void, Void, Boolean> {
#Override
protected Boolean doInBackground(Void... voids) {
// initialize video camera
if (prepareVideoRecorder()) {
// Camera is available and unlocked, MediaRecorder is prepared,
// now you can start recording
mMediaRecorder.start();
} else {
// prepare didn't work, release the camera
releaseMediaRecorder();
//Rückmeldung: Kamera konnte nicht gestartet werden
AlertDialog alertDialog = new AlertDialog.Builder(Record.this).create();
alertDialog.setTitle("Achtung");
alertDialog.setMessage("Kamera konnte nicht gestartet werden. Du kannst trotzdem die Daten aufzeichnen und mir so helfen.");
alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "Okay",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.show();
return false;
}
return true;
}
#Override
protected void onPostExecute(Boolean result) {
if (!result) {
Record.this.finish();
}
}
}
I tried every solution here but non of them worked. Even more confusing for me is that on some devices it works without a problem.
Xperia XZ1 Compact with Android 8.0 and Google Pixel with Android 7.1 throw that problem.
Any advice is appreciated.
Edit: Here is what happens in prepareVideoRecorder:
private boolean prepareVideoRecorder() {
// BEGIN_INCLUDE (configure_preview)
mCamera = CameraHelper.getDefaultCameraInstance();
if(CamcorderProfile.hasProfile(0,CamcorderProfile.QUALITY_QVGA)){
// We need to make sure that our preview and recording video size are supported by the
// camera. Query camera to find all the sizes and choose the optimal size given the
// dimensions of our preview surface.
Camera.Parameters parameters = mCamera.getParameters();
List<Camera.Size> mSupportedPreviewSizes = parameters.getSupportedPreviewSizes();
List<Camera.Size> mSupportedVideoSizes = parameters.getSupportedVideoSizes();
Camera.Size optimalSize = CameraHelper.getOptimalVideoSize(mSupportedVideoSizes, mSupportedPreviewSizes, mPreview.getWidth(), mPreview.getHeight());
// Use the same size for recording profile.
CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_QVGA);
profile.videoFrameWidth = optimalSize.width;
profile.videoFrameHeight = optimalSize.height;
// likewise for the camera object itself.
parameters.setPreviewSize(profile.videoFrameWidth, profile.videoFrameHeight);
mCamera.setDisplayOrientation(90);
mCamera.setParameters(parameters);
try {
// Requires API level 11+, For backward compatibility use {#link setPreviewDisplay}
// with {#link SurfaceView}
mCamera.setPreviewTexture(mPreview.getSurfaceTexture());
} catch (IOException e) {
Log.e(TAG, "Surface texture is unavailable or unsuitable" + e.getMessage());
return false;
}
// END_INCLUDE (configure_preview)
// BEGIN_INCLUDE (configure_media_recorder)
mMediaRecorder = new MediaRecorder();
// Step 1: Unlock and set camera to MediaRecorder
mCamera.unlock();
mMediaRecorder.setOrientationHint(90);
mMediaRecorder.setCamera(mCamera);
// Step 2: Set sources
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
mMediaRecorder.setProfile(profile);
mMediaRecorder.setVideoEncodingBitRate(1000000);
// Step 4: Set output file
mOutputFile = CameraHelper.getOutputMediaFile(getFilesDir().getAbsolutePath());
if (mOutputFile == null) {
return false;
}
mMediaRecorder.setOutputFile(mOutputFile.getPath());
// END_INCLUDE (configure_media_recorder)
// Step 5: Prepare configured MediaRecorder
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
} catch (IOException e) {
Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
releaseMediaRecorder();
return false;
}
return true;
}
else {
return false;
}
}
In your method prepareVideoRecorder(), you should check first whether the profile you want to use, is supported or not -
if(CamcorderProfile.hasProfile()){
// then get profile ....
}
public static boolean hasProfile (int cameraId,
int quality);
If it does not support then you will always get the crash because the profile is not supported on that device. So you need to check first and if supported only then perform rest of the operations.

Need help figuring out why app crashes and stop video is called when I click to start it instead?

The code is supposed to work but when I click on my video button to stop recording I receive a "fatal exception" crash and it shows me that the line mMediaRecorder.stop(); doesn't work.
Here's my code:
private CameraDevice.StateCallback mCameraDeviceStateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice camera) { //camera device member return back to me
mCameraDevice = camera;
// Toast.makeText(getApplicationContext(), "Camera connection made!", Toast.LENGTH_SHORT).show();
// ^indicates camera is connected
if (mIsRecording){
try{
createVideoFileName();
}
catch(IOException e) {
e.printStackTrace();
}
startRecord();
mMediaRecorder.start();
}
else {
startPreview();
}
}
//makes this marshallow version compatible for Android because from Marshallow version and onwards we needed...
//...the permissions required.
private void checkWriteStoragePermission(){
// v check to support applications on devices older than Marshmallow version in Android
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.lollipop) { //support Marshallow or later versions
// v check to see if granted permission
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) ==
PackageManager.PERMISSION_GRANTED) {
mIsRecording = true;
mRecordImageButton.setImageResource(R.drawable.btn_video_busy); //not recording
try {
createVideoFileName(); //was giving an unhandled exception java long error so needed try/catch here
} catch (IOException e) {
e.printStackTrace();
}
startRecord();
mMediaRecorder.start();
}/* else { //check if permission was granted and had been denied
if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
Toast.makeText(this, "app needs to be able to save videos", Toast.LENGTH_SHORT).show();
}
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION_RESULT);
} */
}
else //if running older versions than Marshallow, not going to worry about it, so build "else" statement
{ // supporting old versions of Android
mIsRecording = true;
mRecordImageButton.setImageResource(R.drawable.btn_video_busy); //not recording
try{
createVideoFileName();
}
catch (IOException e){
e.printStackTrace();
}
startRecord();
mMediaRecorder.start();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
createVideoFolder(); //creates the video folder when camera page loads
mMediaRecorder = new MediaRecorder();
mTextureView = (TextureView) findViewById(R.id.textureView);
mRecordImageButton = (ImageButton) findViewById(R.id.videoOnlineImageButton);
mRecordImageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mIsRecording) {
mIsRecording = false;
mRecordImageButton.setImageResource(R.drawable.btn_video_online);
mMediaRecorder.stop(); //<-- FATAL EXCEPTION CRASH
mMediaRecorder.reset();
startPreview(); //< this code says = once it's stops recording TextureView preview still continues
} else {
checkWriteStoragePermission();
}
}
});
}
private void createVideoFolder() {
File movieFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
mVideoFolder = new File(movieFile, "camera2VideoImage");
if(!mVideoFolder.exists()) {
mVideoFolder.mkdirs();
}
}
12-23 22:23:07.509 14045-14045/com.example.name.videoscrolltrial E/MediaRecorder: stop failed: -1007
12-23 22:23:07.510 14045-14045/com.example.name.videoscrolltrial D/AndroidRuntime: Shutting down VM
12-23 22:23:07.511 14045-14045/com.example.name.videoscrolltrial E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.name.videoscrolltrial, PID: 14045
java.lang.RuntimeException: stop failed.
at android.media.MediaRecorder._stop(Native Method)
at android.media.MediaRecorder.stop(MediaRecorder.java:1220)
at com.example.name.videoscrolltrial.Camera$3.onClick(Camera.java:192) //< causes the crash, this is mMediaRecorder.stop();
at android.view.View.performClick(View.java:6308)
at android.view.View$PerformClick.run(View.java:23969)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6823)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1563)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1451)
This code works for phones like Nexus 5X but for my Samsung Galaxy Note 8 it doesn't just gives a crash. I don't understand what I have to do to make the code compatible for ALL phones?
You can't stop the mediaRecorder without starting it first.

Android camera preview freezes suddenly

I have implemented an android camera with the help of official developer.android.com tutorial. The app is working fine sometimes but about 3/5 of times the preview of the camera freezes after some rotation and clicking the buttons or even without these works (other elements don't freeze). The cutest part is that when I debug the application the preview doesn't stuck but when I want to run the app normally sometimes the problem happens.
Here is my fullScreen Class which is consist of the codes that android studio generated for fullScreen activity and the codes for implementing surfaceHolder.Callback and camera stuff.
public class CameraActivity extends Activity implements SurfaceHolder.Callback {
... // some constants here
private Camera mCamera;
private SurfaceHolder mHolder;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
SurfaceView cameraSufaceView = (SurfaceView) findViewById(R.id.camera_preview);
// Accessing front camera to take picture
mCamera = openFrontFacingCameraGingerbread();
if (mCamera != null) {
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = cameraSufaceView.getHolder();
mHolder.addCallback(this);
} else {
// Alter user
}
/**
* Gets an instance of front facing camera if available
*/
#SuppressWarnings("deprecation")
private Camera openFrontFacingCameraGingerbread() {
int cameraCount;
Camera cam = null;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
cameraCount = Camera.getNumberOfCameras();
for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
Camera.getCameraInfo(camIdx, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
try {
cam = Camera.open(camIdx);
} catch (RuntimeException e) {
Log.e(TAG, "Camera failed to open: " + e.getLocalizedMessage());
}
}
}
return cam;
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// start preview with new settings
try {
// mCamera.setDisplayOrientation(needs degree here);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
releaseCamera();
}
#Override
protected void onPause() {
super.onPause();
releaseCamera();
}
#Override
protected void onResume() {
super.onResume();
if (mCamera == null)
mCamera = openFrontFacingCameraGingerbread();
}
private void releaseCamera() {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release(); // release the camera for other applications
mCamera = null;
}
}
When this problem happens some errors appear in the LogCat but they are not really informative. here are they:
26893-26893/com.naviiid.retinaflash E/art﹕ No implementation found for void java.lang.Runtime.appStartupEnd() (tried Java_java_lang_Runtime_appStartupEnd and Java_java_lang_Runtime_appStartupEnd__)
09-16 01:34:09.336 26893-26893/com.naviiid.retinaflash E/ActivityThread﹕ appStartupEnd :
java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java)
at android.app.ActivityThread.appStartupEnd(ActivityThread.java:305)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2819)
at android.app.ActivityThread.access$900(ActivityThread.java:177)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1448)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5942)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
Caused by: java.lang.UnsatisfiedLinkError: No implementation found for void java.lang.Runtime.appStartupEnd() (tried Java_java_lang_Runtime_appStartupEnd and Java_java_lang_Runtime_appStartupEnd__)
at java.lang.Runtime.appStartupEnd(Native Method)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java)
            at android.app.ActivityThread.appStartupEnd(ActivityThread.java:305)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2819)
            at android.app.ActivityThread.access$900(ActivityThread.java:177)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1448)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:145)
            at android.app.ActivityThread.main(ActivityThread.java:5942)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
The only clue that I have found so far is that sometimes android calls onPause method even if the activity isn't paused. For getting instance of the camera again I call openFrontFacingCameraGingerbread() in onResume method.

Android animation lagging

Please scroll down to the "EDIT" :)
I'm trying to understand some basic android animation programming using Android Studio, and I have followed some tutorials on the internet.
I already know some basic java programming, but I have a problem with my "copy/paste app" I made.
This is my MainActivity:
public class MainActivity extends ActionBarActivity {
private Button play;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
play = (Button) findViewById(R.id.play_button);
play.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent startGame = new Intent("com.abc.test.DRAWGAME2");
startActivity(startGame);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}}
This is DrawGame2.java:
public class DrawGame2 extends Activity implements View.OnTouchListener {
private MyView surfaceView;
private float y;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
surfaceView = new MyView(this);
surfaceView.setOnTouchListener(this);
setContentView(surfaceView);
}
#Override
protected void onPause() {
super.onPause();
surfaceView.pause();
}
#Override
protected void onResume() {
super.onResume();
surfaceView.resume();
}
#Override
public boolean onTouch(View v, MotionEvent me) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
switch (me.getAction()){
case MotionEvent.ACTION_DOWN:
y = me.getY();
break;
case MotionEvent.ACTION_UP:
y = me.getY();
break;
case MotionEvent.ACTION_MOVE:
y = me.getY();
break;
}
return true;
}
public class MyView extends SurfaceView implements Runnable {
private Thread thread = null;
private SurfaceHolder holder;
private boolean isRunning = false;
public MyView(Context context) {
super(context);
holder = getHolder();
y = 0;
}
public void run() {
while (isRunning) {
if (!holder.getSurface().isValid()) {
continue;
}
Canvas canvas = holder.lockCanvas();
canvas.drawRGB(02,02,150);
if (y != 0){
Bitmap test = BitmapFactory.decodeResource(getResources(),R.drawable.greenball);
canvas.drawBitmap(test, canvas.getWidth()/2 - test.getWidth()/2, y, null);
}
holder.unlockCanvasAndPost(canvas);
}
}
public void pause() {
isRunning = false;
while (true) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
thread = null;
}
public void resume() {
isRunning = true;
thread = new Thread(this);
thread.start();
}
}}
Logcat:
02-12 11:01:06.676 1972-1972/com.abc.test I/art﹕ Not late-enabling -Xcheck:jni (already on)
02-12 11:01:06.881 1972-1990/com.abc.test D/OpenGLRenderer﹕ Render dirty regions requested: true
02-12 11:01:06.882 1972-1972/com.abc.test D/﹕ HostConnection::get() New Host Connection established 0xa686fb60, tid 1972
02-12 11:01:06.917 1972-1972/com.abc.test D/Atlas﹕ Validating map...
02-12 11:01:07.007 1972-1990/com.abc.test D/﹕ HostConnection::get() New Host Connection established 0xa686fd90, tid 1990
02-12 11:01:07.037 1972-1990/com.abc.test I/OpenGLRenderer﹕ Initialized EGL, version 1.4
02-12 11:01:07.102 1972-1990/com.abc.test D/OpenGLRenderer﹕ Enabling debug mode 0
02-12 11:01:07.126 1972-1990/com.abc.test W/EGL_emulation﹕ eglSurfaceAttrib not implemented
02-12 11:01:07.126 1972-1990/com.abc.test W/OpenGLRenderer﹕ Failed to set EGL_SWAP_BEHAVIOR on surface 0xa6814940, error=EGL_SUCCESS
02-12 11:01:07.705 1972-1990/com.abc.test W/EGL_emulation﹕ eglSurfaceAttrib not implemented
02-12 11:01:07.705 1972-1990/com.abc.test W/OpenGLRenderer﹕ Failed to set EGL_SWAP_BEHAVIOR on surface 0xa6814940, error=EGL_SUCCESS
02-12 11:01:12.571 1972-1990/com.abc.test W/EGL_emulation﹕ eglSurfaceAttrib not implemented
02-12 11:01:12.571 1972-1990/com.abc.test W/OpenGLRenderer﹕ Failed to set EGL_SWAP_BEHAVIOR on surface 0xa5a69ba0, error=EGL_SUCCESS
02-12 11:01:16.892 1972-1972/com.abc.test I/Choreographer﹕ Skipped 263 frames! The application may be doing too much work on its main thread.
02-12 11:01:16.899 1972-2270/com.abc.test D/﹕ HostConnection::get() New Host Connection established 0xa5dfcc10, tid 2270
The problem with this app is that the animation is really laggy, and I can't figure out why!
I have tried to make the same animation with a simple rectangle, but the lag is still there.
The problem isn't the OnTouchListener, because I've tried to just increase the y value by 1 with each loop in the run method (while disabling the OnTouchListener), but it is still lagging.
I have tried with different emulators (Lollipop, Kitkat) and on my Samsung Galaxy S3 (Jelly Bean).
Are there any wise people out there that can help me with this problem? :)
Have a great day!
EDIT:
Okay, so I applied the answers I got, and now it runs smoothly, ON MY Samung Galaxy S3!
The lagging is still there on my emulator though. I've installed HAXM and the emulator runs smoothly out of the app I've created, but as soon as I launch the app and press the "PLAY" button, the animation lags when I interact with the app.
This is the properties for my emulator:
Name: Nexus_5_API_21
CPU/ABI: Intel Atom (x86)
hw.gpu.enabled: yes
Path: C:\Users\User\.android\avd\Nexus_5_API_21.avd
Target: Android 5.0.1 (API level 21)
Skin: nexus_5
SD Card: 100M
Snapshot: no
hw.lcd.density: 480
hw.dPad: no
avd.ini.encoding: UTF-8
hw.camera.back: none
disk.dataPartition.size: 200M
runtime.network.latency: none
skin.dynamic: no
hw.keyboard: yes
runtime.network.speed: full
hw.device.hash2: MD5:2fa0e16c8cceb7d385183284107c0c88
hw.ramSize: 1536
tag.id: default
tag.display: Default
hw.sdCard: yes
hw.device.manufacturer: Google
hw.mainKeys: no
hw.accelerometer: yes
hw.trackBall: no
hw.device.name: Nexus 5
hw.sensors.proximity: yes
hw.battery: yes
AvdId: Nexus_5_API_21
hw.sensors.orientation: yes
hw.audioInput: yes
hw.camera.front: none
hw.gps: yes
avd.ini.displayname: Nexus 5 API 21
snapshot.present: no
vm.heapSize: 64
runtime.scalefactor: auto
As far as I can see, your problem is in the onTouch() method, in which you have this code:
try{
Thread.sleep(50);
}catch (InterruptedException e){
e.printStackTrace();
}
Which will sleep the MAIN thread, meaning that everything will make the entire application hold up for 50 milliseconds.
So try to remove that.
Decoding resources are also not performance friendly. You should decode bitmap earlier and reuse it while drawing. Why you do not use onDraw method ?

Black Screen When App Opens

I keep getting this black screen when ever I open my app, the only way to get rid of it is to press the back button, then again go to the app. I was told by my friend that it is going into deadlock! but I do not think because when I checked the logcat it shows the below log messages.
View
private boolean mGameIsRunning;
public void surfaceCreated(SurfaceHolder holder) {
// Your own start method.
start();
}
public void start() {
if (!mGameIsRunning) {
thread.initLevel();
thread.setRunning(true);
thread.start();
mGameIsRunning = true;
} else {
thread.onResume();
thread.initLevel();
thread.setRunning(true);
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(TAG, "Surface is being destroyed");
// tell the thread to shut down and wait for it to finish
// this is a clean shutdown
boolean retry = true;
thread.setRunning(false);
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Log.d(TAG, "Thread was shut down cleanly");
}
Thread
private Object mPauseLock = new Object();
private boolean mPaused;
#Override
public void run() {
Canvas canvas;
Log.d(TAG, "Starting game loop");
while (running) {
canvas = null;
// try locking the canvas for exclusive pixel editing
// in the surface
try {
canvas = this.mSurfaceHolder.lockCanvas();
synchronized (mSurfaceHolder) {
mStartTime = System.currentTimeMillis();
mElapsedTime = System.currentTimeMillis() - mStartTime;
this.updateGame();
this.onDraw(canvas);
}
synchronized(mPauseLock){
while (mPaused) {
try {
mPauseLock.wait();
} catch (InterruptedException e) {
}
}
}
} finally {
// in case of an exception the surface is not left in
// an inconsistent state
if (canvas != null) {
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
} // end finally
}
}
public void onPause() {
synchronized (mPauseLock) {
mPaused = true;
}
}
public void onResume() {
synchronized (mPauseLock) {
mPaused = false;
mPauseLock.notifyAll();
}
}
Log
07-08 17:24:41.735: DEBUG/Hitman(3221): View added
07-08 17:24:41.895: DEBUG/(3221): Enemies Spawed
07-08 17:24:41.934: DEBUG/(3221): Starting game loop
07-08 17:24:42.165: INFO/ActivityManager(66): Displayed activity com.android.hitmanassault/.Hitman: 1384 ms (total 1384 ms)
07-08 17:24:46.164: DEBUG/(3221): Enemies Spawed
07-08 17:24:48.914: INFO/ActivityManager(66): Start proc com.android.settings for broadcast com.android.settings/.widget.SettingsAppWidgetProvider: pid=3228 uid=1000 gids={3002, 3001, 3003}
07-08 17:24:48.914: INFO/ActivityManager(66): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10200000 cmp=com.android.launcher/.Launcher }
07-08 17:24:48.924: DEBUG/PhoneWindow(3221): couldn't save which view has focus because the focused view com.android.hitmanassault.HitmanView#44d99528 has no id.
07-08 17:24:48.954: INFO/WindowManager(66): Setting rotation to 0, animFlags=0
07-08 17:24:49.014: INFO/ActivityManager(66): Config changed: { scale=1.0 imsi=310/260 loc=en_US touch=3 keys=2/1/2 nav=3/1 orien=1 layout=34}
07-08 17:24:49.275: DEBUG/(3221): Surface is being destroyed
07-08 17:24:49.285: DEBUG/(3221): Thread was shut down cleanly
07-08 17:24:49.694: DEBUG/ddm-heap(3228): Got feature list request
07-08 17:24:49.754: WARN/IInputConnectionWrapper(3221): showStatusIcon on inactive InputConnection
07-08 17:24:51.315: DEBUG/dalvikvm(66): GC freed 2325 objects / 114696 bytes in 122ms
07-08 17:24:58.234: INFO/ActivityManager(66): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.hitmanassault/.HitmanTitle }
07-08 17:24:58.284: INFO/WindowManager(66): Setting rotation to 1, animFlags=0
07-08 17:24:58.354: INFO/ActivityManager(66): Config changed: { scale=1.0 imsi=310/260 loc=en_US touch=3 keys=2/1/2 nav=3/1 orien=2 layout=34}
07-08 17:24:58.554: DEBUG/(3221): Enemies Spawed
07-08 17:24:58.945: WARN/IInputConnectionWrapper(144): showStatusIcon on inactive InputConnection
07-08 17:25:00.604: DEBUG/dalvikvm(66): GC freed 1403 objects / 71832 bytes in 103ms
Activity Class:
#Override
public boolean onCreateOptionsMenu(Menu menu){
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.game_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId()){
case R.id.menu_restart:
startActivity(new Intent(this, Hitman.class));
return true;
case R.id.menu_scores:
startActivity(new Intent(this, HitmanScores.class));
return true;
case R.id.menu_help:
startActivity(new Intent(this, HitmanHelp.class));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new CanvasSurfaceView(this));
Log.d(TAG, "View added");
}
Does rotating the display cause it to refresh (in emulator: CTRL+F12)? If so then you have to override onResume() in your activity and have it restart whatever it is you set up that might not be being called. It could be that you just need to call view.invalidate() from the activity onResume()? You don't show code from your activity so I'm unsure.
In the code I saw, you should use this.postInvalidate() (same as invalidate() but for from a different thread) instead of this.onDraw(canvas) and have it call this.onDraw() on its own in the UI thread, as opposed to in your thread.
Where do you initialize your thread? Try doing so in surfaceCreated( ) instead of the surfaceView consturctor (which is where I think you did it..)
public void surfaceCreated(SurfaceHolder holder) {
// Restart draw thread
Thread.State state = thread.getState();
if(state == Thread.State.TERMINATED)
thread = new MyThread(getHolder(), getContext());
thread.setRunning(true);
thread.start();
}

Categories

Resources