How to deal with E/JavaBinder: FAILED BINDER TRANSACTION that crashes the app?
I am making an android game using a SurfaceView.
I am also using a dedicated thread for the infinite Game-Loop itself, which contains both an update() method, as well as a draw() method.
The update() method updates characters position(logic) and sprites, while the draw() method draws to the canvas.
The dedicated thread handles both update() and draw() since they need to be synchronized.
The onTouchEvents (user clicks) are handled by the main thread.
Although I cannot tell for sure, I suspect that I am getting this error: E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! , because
both the draw() method and the update() method call other methods that call other methods and so on.. resulting in an almost a recursive behavior.
For example my update() method, calls characterOne.update().. which then calls characterOneSpells.update() which then calls spellOne.update() and so on... same thing for the draw(). I suspect that this overflows the bind buffer or something like that.. I am not sure.. and all of this is happening in an infinite loop infinite amount of times.
Note that I took this approach ( methods call methods that call other methods) because logically it made sense to me that a character should be responsible to draw itself, and a spell should be responsible to draw itself, rather than the character be responsible to draw and update the spells and so on. It made sense to me that every object should be responsible to draw itself and update itself, and that is my reasoning, I might be wrong, please let me know what you think.
Now, I am new to game making, and in fact this is my first game, so please take it easy on me, I am trying to learn!
Sample of my code and the error log can be found below.
Any insight to why I am getting this E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! and how to fix it would be very much appreciated! Also feel free to suggest a better design or approach, since I am trying to learn.
Thank you!
I marked the important parts of the code with ** Important ** comment to make things easier.`
ERROR LOG:
11-17 17:07:30.132 934-1460/? E/JavaBinder: !!! FAILED BINDER TRANSACTION !!!
11-17 17:07:30.388 1451-1451/? E/RecyclerView: No adapter attached; skipping layout
11-17 17:07:32.328 934-992/? E/InputDispatcher: channel '329e61e3 com.amazon.firelauncher/com.amazon.firelauncher.Launcher (server)' ~ Channel is unrecoverably broken and will be disposed!
11-17 17:07:32.407 146-146/? E/lowmemorykiller: Error opening /proc/2493/oom_score_adj; errno=2
11-17 17:07:32.442 934-1011/? E/WifiService: Multicaster binderDied
11-17 17:07:32.462 146-146/? E/lowmemorykiller: Error opening /proc/2493/oom_score_adj; errno=2
11-17 17:07:32.464 146-146/? E/lowmemorykiller: Error opening /proc/2493/oom_score_adj; errno=2
11-17 17:07:32.464 146-146/? E/lowmemorykiller: Error opening /proc/1217/oom_score_adj; errno=2
11-17 17:07:36.426 6868-6868/? E/cr_AWVDeploymentClient: Chromium Version = v59 key doesn't exist. So, default version config will be used.
11-17 17:07:36.428 6868-6868/? E/cr_AWVDeploymentClient: Default device config doesn't exist
11-17 17:07:39.313 934-992/? E/InputDispatcher: channel '11e88fc0 info.evyatar.mystrategygame/info.evyatar.mystrategygame.MainActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
11-17 17:07:40.905 7010-7051/? E/SQLiteLog: (283) recovered 44 frames from WAL file /data/user/0/com.amazon.firelauncher/databases/producer.db-wal
11-17 17:07:41.091 7010-7059/? E/SQLiteLog: (283) recovered 90 frames from WAL file /data/user/0/com.amazon.firelauncher/databases/CardDeviceAgentDB-wal
11-17 17:07:43.558 7010-7010/? E/RecyclerView: No adapter attached; skipping layout
11-17 17:07:43.622 7089-7089/? E/TimeoutManagerClient: bindService() Failed to bind to ECService
11-17 17:07:43.631 7165-7165/? E/Dagger2: ApplicationModule context already set
11-17 17:07:44.924 7089-7311/? E/...iceDataCommunication: Got a RemoteMAPException
com.amazon.identity.auth.device.framework.RemoteMAPException: com.amazon.identity.auth.device.api.DeviceDataStoreException: Key ke_device was not found in the device data store. This device does not support ke_device. This error is expected if the device not support ke_device.
at com.amazon.identity.auth.device.framework.SecureContentResolver.acquireContentProviderClient(SecureContentResolver.java:118)
at com.amazon.identity.auth.device.devicedata.DeviceDataCommunication.retriveValueFromCentralStore(DeviceDataCommunication.java:59)
at com.amazon.identity.auth.device.devicedata.DeviceDataCommunication.getValue(DeviceDataCommunication.java:52)
at com.amazon.identity.auth.device.devicedata.DeviceDataStoreSystemPropertyDecorator.getValue(DeviceDataStoreSystemPropertyDecorator.java:52)
at com.amazon.identity.auth.device.api.DeviceDataStore.getValue(DeviceDataStore.java:96)
at com.amazon.avod.identity.DeviceProperties.isKidsEditionDevice(DeviceProperties.java:374)
at com.amazon.avod.identity.DeviceProperties.initialize(DeviceProperties.java:201)
at com.amazon.avod.core.ApplicationComponents$InitializeDeviceProperties.initialize(ApplicationComponents.java:543)
at com.amazon.avod.core.ApplicationComponents$InitializeRunnable.run(ApplicationComponents.java:787)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: com.amazon.identity.auth.device.api.DeviceDataStoreException: Key ke_device was not found in the device data store. This device does not support ke_device. This error is expected if the device not support ke_device.
at com.amazon.identity.auth.device.devicedata.DeviceDataCommunication$1.useContentProviderClient(DeviceDataCommunication.java:93)
at com.amazon.identity.auth.device.devicedata.DeviceDataCommunication$1.useContentProviderClient(DeviceDataCommunication.java:61)
at com.amazon.identity.auth.device.framework.SecureContentResolver.acquireContentProviderClient(SecureContentResolver.java:112)
at com.amazon.identity.auth.device.devicedata.DeviceDataCommunication.retriveValueFromCentralStore(DeviceDataCommunication.java:59)
at com.amazon.identity.auth.device.devicedata.DeviceDataCommunication.getValue(DeviceDataCommunication.java:52)
at com.amazon.identity.auth.device.devicedata.DeviceDataStoreSystemPropertyDecorator.getValue(DeviceDataStoreSystemPropertyDecorator.java:52)
at com.amazon.identity.auth.device.api.DeviceDataStore.getValue(DeviceDataStore.java:96)
at com.amazon.avod.identity.DeviceProperties.isKidsEditionDevice(DeviceProperties.java:374)
at com.amazon.avod.identity.DeviceProperties.initialize(DeviceProperties.java:201)
at com.amazon.avod.core.ApplicationComponents$InitializeDeviceProperties.initialize(ApplicationComponents.java:543)
at com.amazon.avod.core.ApplicationComponents$InitializeRunnable.run(ApplicationComponents.java:787)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
11-17 17:07:45.701 7010-7085/? E/...iceDataCommunication: Got a RemoteMAPException
com.amazon.identity.auth.device.framework.RemoteMAPException: com.amazon.identity.auth.device.api.DeviceDataStoreException: Key re_device was not found in the device data store. This device does not support re_device. This error is expected if the device not support re_device.
at com.amazon.identity.auth.device.framework.SecureContentResolver.acquireContentProviderClient(SecureContentResolver.java:118)
at com.amazon.identity.auth.device.devicedata.DeviceDataCommunication.retriveValueFromCentralStore(DeviceDataCommunication.java:59)
at com.amazon.identity.auth.device.devicedata.DeviceDataCommunication.getValue(DeviceDataCommunication.java:52
at java.lang.Thread.run(Thread.java:818)
Caused by: com.amazon.identity.auth.device.api.DeviceDataStoreException: Key re_device was not found in the device data store. This device does not support re_device. This error is expected if the device not support re_device.
at com.amazon.identity.auth.device.devicedata.DeviceDataCommunication$1.useContentProviderClient(DeviceDataCommunication.java:93)
at com.amazon.identity.auth.device.devicedata.DeviceDataCommunication$1.useContentProviderClient(DeviceDataCommunication.java:61)
at com.amazon.firelauncher.services.MapCache.updateDeviceData(MapCache.java:579)
at com.amazon.firelauncher.services.MapCache.access$700(MapCache.java:47)
at com.amazon.firelauncher.services.MapCache$3.run(MapCache.java:491)
at com.amazon.firelauncher.services.BackgroundExecutor$InternalRunnable.run(BackgroundExecutor.java:180)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
11-17 17:07:45.930 7343-7343/? E/SQLiteLog: (283) recovered 120 frames from WAL file /data/securedStorageLocation/com.amazon.providers.contentsupport/contentsupport.db-wal
11-17 17:07:45.979 7343-7343/? E/SQLiteLog: (284) automatic index on languages(packageId)
11-17 17:07:46.007 7343-7343/? E/SQLiteLog: (284) automatic index on languages(packageId)
11-17 17:07:47.386 7010-7417/? E/F_C.ArcusRemoteConfigur: No valid offline remote setting found for the current device, not setting default
java.lang.Exception: Error getting the baseline setting for Arcus config cms
at com.amazon.firelauncher.reccardproducer.settings.OfflineSetting.value(OfflineSetting.java:106)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.os.HandlerThread.run(HandlerThread.java:61)
Caused by: java.lang.Exception: Exception reading from cms/baseline.json
at com.amazon.firelauncher.reccardproducer.settings.JSONFile.value(JSONFile.java:43)
at com.amazon.firelauncher.reccardproducer.settings.JSONFile.value(JSONFile.java:14)
at com.amazon.firelauncher.reccardproducer.settings.OfflineSetting.value(OfflineSetting.java:88)
at com.amazon.firelauncher.reccardproducer.settings.OfflineSetting.value(OfflineSetting.java:22)
at com.amazon.firelauncher.reccardproducer.arcus.ArcusRemoteConfiguration$1.map(ArcusRemoteConfiguration.java:67)
at com.amazon.firelauncher.reccardproducer.arcus.ArcusRemoteConfiguration$1.map(ArcusRemoteConfiguration.java:60)
at com.amazon.firelauncher.reccardproducer.arcus.ArcusRemoteConfiguration.initialize(ArcusRemoteConfiguration.java:117)
at com.amazon.firelauncher.reccardproducer.cards.RecommendationsController.getInstance(RecommendationsController.java:111)
at com.amazon.firelauncher.reccardproducer.ProducerService.onHandleIntent(ProducerService.java:57)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.os.HandlerThread.run(HandlerThread.java:61)
Caused by: java.io.FileNotFoundException: cms/baseline.json
at android.content.res.AssetManager.openAsset(Native Method)
at android.content.res.AssetManager.open(AssetManager.java:313)
at android.content.res.AssetManager.open(AssetManager.java:287)
at com.amazon.firelauncher.reccardproducer.settings.JSONFile.value(JSONFile.java:29)
at com.amazon.firelauncher.reccardproducer.settings.JSONFile.value(JSONFile.java:14)
at com.amazon.firelauncher.reccardproducer.settings.OfflineSetting.value(OfflineSetting.java:88)
at com.amazon.firelauncher.reccardproducer.cards.RecommendationsController.getInstance(RecommendationsController.java:111)
at com.amazon.firelauncher.reccardproducer.ProducerService.onHandleIntent(ProducerService.java:57)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.os.HandlerThread.run(HandlerThread.java:61)
11-17 17:07:47.400 7010-7417/? E/F_C.FireDeviceAttribute: BuildNumber is not a valid String attribute (wrong type: Integer)
11-17 17:07:47.416 7010-7417/? E/F_C.ArcusParameters: Exception getting attribute %s, no attribute added
java.lang.NullPointerException: attrValue cannot be null
at com.amazonaws.mobileconnectors.remoteconfiguration.internal.gear.Checks.checkNotNull(Checks.java:20)
at com.amazonaws.mobileconnectors.remoteconfiguration.internal.AttributesImpl.addAttributePrivate(AttributesImpl.java:193)
at com.amazonaws.mobileconnectors.remoteconfiguration.internal.AttributesImpl.addAttribute(AttributesImpl.java:103)
at com.amazon.firelauncher.reccardproducer.arcus.ArcusParameters.decorateManager(ArcusParameters.java:87)
at com.amazon.firelauncher.reccardproducer.arcus.ArcusRemoteConfiguration.initialize(ArcusRemoteConfiguration.java:119)
at com.amazon.firelauncher.reccardproducer.cards.RecommendationsController.getInstance(RecommendationsController.java:111)
at com.amazon.firelauncher.reccardproducer.ProducerService.onHandleIntent(ProducerService.java:57)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.os.HandlerThread.run(HandlerThread.java:61)
Sample Code
public class GameLoop extends SurfaceView implements SurfaceHolder.Callback {
private Context myContext;
private SurfaceHolder mySurfaceHolder;
private Bitmap backgroundImg;
private int screenW = 1;
private int screenH = 1;
private boolean running = false;
private boolean onTitleScreen = true;
private GameLoopThread thread;
private int backgroundOrigW;
private int backgroundOrigH;
private float scaleW;
private float scaleH;
private float drawScaleW;
private float drawScaleH;
private int fingerX, fingerY;
private boolean isDragging = false;
SingltonAssetsObject mSingltonAssetsObject;
private boolean gameOver;
Point userClickPoint;
//Characters
CharacterTypeOne characterFighterOne,characterFighterTwo,characterFighterThree;
CharacterTypeTwo CharacterMage;
public GameLoop(Context context, AttributeSet attrs) {
super(context, attrs);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
//init clickRectangle
userClickPoint = new Point();
//creates the gameLoop thread DRAW THREAD
thread = new GameLoopThread(holder,context);
setFocusable(true);
}
public void initCharacters(){
mSingltonAssetsObject = SingltonAssetsObject.getInstance(myContext,scaleW,scaleH);
characterFighterOne = new characterFighterOne(myContext,1000,1,150,350,100,15,1.0,scaleW,scaleH,drawScaleW,drawScaleH,screenW,screenH);
characterFighterTwo = new characterFighterOne(myContext,1001,67,350,350,100,15,1.0,scaleW,scaleH,drawScaleW,drawScaleH,screenW,screenH);
characterFighterThree = new characterFighterOne(myContext,1002,99,550,350,1000,15,1.0,scaleW,scaleH,drawScaleW,drawScaleH,screenW,screenH);
characterMage = new characterMage(myContext,50,28,650,250,100,15,0.1,scaleW,scaleH,drawScaleW,drawScaleH,screenW,screenH);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
return thread.doTouchEvent(event);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
thread.setSurfaceSize(width, height);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
thread.setRunning(true);
if (thread.getState() == Thread.State.NEW) {
thread.start();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
thread.setRunning(false);
}
class GameLoopThread extends Thread{
public GameLoopThread(SurfaceHolder surfaceHolder, Context context){
//initialzied in inner class and not outter because this variable will act as a lock and will be shard with all threads
mySurfaceHolder = surfaceHolder;
myContext = context;
//the background image of the title screen
backgroundImg = BitmapFactory.decodeResource(context.getResources(), R.drawable.title);
backgroundOrigW = backgroundImg.getWidth();
backgroundOrigH = backgroundImg.getHeight();
}
//This method is the main game loop
public void run() {
while (running) {
try { //lock canvas for drawing
c = mySurfaceHolder.lockCanvas(null);
synchronized (mySurfaceHolder) {
if (!gameOver)
{
//** important ***
updateAnimationsAndPosition();
}
// **important **
draw(c);
}
} finally {
if (c != null) { //unlock canvas
mySurfaceHolder.unlockCanvasAndPost(c);
}
}
} //while loop ends
} //run Method ends (gameLOOP)
//This method will draw everything to the screen
public void draw(Canvas canvas){
canvas.drawBitmap(backgroundImg, 0, 0, null);
if (!onTitleScreen) {
/* **Important**
Note: characterFighterOne.draw(canvas) calls spells.draw(canvas)
which calls spellOne.draw(canvas).. which call spellIndicartor.draw(canvas)
and so on... might be cauing the isssue?*/
characterFighterOne.draw(canvas);
characterFighterTwo.draw(canvas);
characterFighterThree.draw(canvas);
characterMage.draw(canvas);
}
}
//This method updates the animations, for example changes image every tick
public void updateAnimationsAndPosition(){
if(!onTitleScreen){
/***Important**
Note: characterFighterOne.updateAnimationsAndPosition() calls spells.update()
which calls spellOne.update().. which call spellIndicartor.update()
and so on... might be causing the issue?*/
characterFighterOne.updateAnimationsAndPosition();
characterFighterTwo.updateAnimationsAndPosition();
characterFighterThree.updateAnimationsAndPosition();
characterMage.updateAnimationsAndPosition();
}
}
public void setSurfaceSize(int width, int height) {
synchronized (mySurfaceHolder) {
screenW = width;
screenH = height;
backgroundImg = Bitmap.createScaledBitmap(backgroundImg, width, height, true);
drawScaleW = (float) screenW / 960; //screen/background width image
drawScaleH = (float) screenH / 640;
}
}
//This method is in charge of user input ( clicks on screen, and how to respond to them)
public boolean doTouchEvent(MotionEvent event){
if(!onTitleScreen){
characterFighterOne.doTouchEvent(event);
characterFighterTwo.doTouchEvent(event);
characterFighterThree.doTouchEvent(event);
characterMage.doTouchEvent(event);
userClickPoint.set((int)event.getX(),(int)event.getY());
}
synchronized (mySurfaceHolder) {
int eventaction = event.getAction();
int X = (int)event.getX();
int Y = (int)event.getY();
switch (eventaction ) {
case MotionEvent.ACTION_DOWN:
if(!gameOver){
fingerX = X;
fingerY = Y;
if (!onTitleScreen) {
}
}
break;
case MotionEvent.ACTION_MOVE:// used for dragging purposes
break;
case MotionEvent.ACTION_UP:
//Here I load all the images to memory ( while on the titleScreen normal size & scaled, find a better place, maybe OnCreate, leave for now)
if (onTitleScreen) {
backgroundImg = BitmapFactory.decodeResource(myContext.getResources(), R.drawable.background);
backgroundImg = Bitmap.createScaledBitmap(backgroundImg, screenW, screenH, true);
onTitleScreen = false;
scaleW = (float) screenW/ (float) backgroundOrigW;
scaleH = (float) screenH/ (float) backgroundOrigH;
initCharacters();
}
if (gameOver) {
gameOver = false;
}
break;
}
}
return true;
}
//This method enables and disables the Thread
public void setRunning(boolean b) {
running = b;
}
}
}
Related
In my scenario, I have developed CustomSeekbar long back ago. Now, due to Android X version update, my application getting crash “android.view.InflateException: Binary XML file line”, based on my code analysis, I found the issue happening by overriden setProgress() – which is called from ProgressBar's constructor – and there we are calling onSizeChanged().
As of now nothing much reference about this issue in developer community. If any one knows about this issue, Please help me on this.
Stack Trace
2020-06-13 15:36:44.462 25054-25054/com.goom.project_532 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.goom.project_532, PID: 25054
android.view.InflateException: Binary XML file line #120 in com.goom.project_532:layout/fragment_one_control: Binary XML file line #58 in com.goom.project_532:layout/fragment_two_control:: Error inflating class com.kimso.sims.CustomSeekBar
Caused by: android.view.InflateException: Binary XML file line #58 in com.goom.project_532:layout/fragment_two_control:: Error inflating class com.kimso.sims.CustomSeekBar
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at android.view.LayoutInflater.createView(LayoutInflater.java:854)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1006)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:961)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1123)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1084)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1126)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1084)
at android.view.LayoutInflater.parseInclude(LayoutInflater.java:1263)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1119)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1084)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1126)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1084)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1126)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1084)
at android.view.LayoutInflater.inflate(LayoutInflater.java:682)
at android.view.LayoutInflater.inflate(LayoutInflater.java:534)
at com.semcon.jimsa.cfx.fragment.gymControlFragment.onCreateView(gymControlFragment.java:407)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2439)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1460)
at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:802)
at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
at androidx.fragment.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3273)
at androidx.fragment.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3229)
at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:201)
at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:620)
at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:178)
at com.semcon.jimsa.roboguicehelper.KubaAppCompatActivity.onStart(KubaAppCompatActivity.java:141)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1433)
at android.app.Activity.performStart(Activity.java:7978)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3512)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2175)
2020-06-13 15:36:44.464 25054-25054/com.goom.project_532 E/AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:7860)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1075)
Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'void java.util.List.clear()' on a null object reference
at android.widget.AbsSeekBar.updateGestureExclusionRects(AbsSeekBar.java:1001)
at android.widget.AbsSeekBar.setThumbPos(AbsSeekBar.java:985)
at android.widget.AbsSeekBar.updateThumbAndTrackPos(AbsSeekBar.java:878)
at android.widget.AbsSeekBar.updateDrawableBounds(AbsSeekBar.java:1942)
at android.widget.ProgressBar.onSizeChanged(ProgressBar.java:2196)
at android.widget.AbsSeekBar.onSizeChanged(AbsSeekBar.java:837)
at com.kimso.sims.CustomSeekBar.onSizeChanged(jimsaSeekBar.java:242)
at com.kimso.sims.CustomSeekBar.setProgressInternally(jimsaSeekBar.java:435)
at com.kimso.sims.CustomSeekBar.setProgress(jimsaSeekBar.java:312)
at android.widget.ProgressBar.<init>(ProgressBar.java:376)
at android.widget.AbsSeekBar.<init>(AbsSeekBar.java:184)
at android.widget.SeekBar.<init>(SeekBar.java:89)
at android.widget.SeekBar.<init>(SeekBar.java:85)
at android.widget.SeekBar.<init>(SeekBar.java:81)
at com.kimso.sims.CustomSeekBar.<init>(jimsaSeekBar.java:82)
... 48 more
You are trying to set progress and call "onSizeChanged" at the same time in the constructor, before the view is attached to its parent and a window. That is not possible and you're getting a NullPointerException because of this issue. Try setting the progress on View.onAttachedToWindow() method by overriding it instead.
Edit: Well you can override the method in your CustomSeekBar if you just
write "onAttachedToWindow()" in the editor, just like you did at "onSizeChanged". Also you don't need to override "onSizeChanged", in fact that causes a wrong behavior in the code. Swapping width and height may not work there reliably.
Sample code would look like this I presume:
#Override
protected void onAttachedToWindow()
{
super.onAttachedToWindow();
// I believe you are trying to change the width-height depending on the orientation,
// so if the orientation is vertical you can swap the width and height.
// Remember this in the view though, so you wouldn't accidentally change it
// multiple times. Or, if you change it outside of the view lifecycle
// in the code, make sure to reset the state so you can put width-height
// properly again.
// This holds if the width-height change is applied.
// Define this as "private boolean layoutParametersChanged"
// at the top of the class.
if (!layoutParametersChanged)
{
// Mark as changed for the initial process.
layoutParametersChanged = true;
// I assume "1" stands for "Vertical" in your code.
// If it is horizontal, you shouldn't do a change.
if (mOrientation == 1)
{
// If you are using "wrap_content" or "match_parent" don't use them here.
// This check determines a fixed width and height, such as "60dp 60dp"
// for "layout_width" and "layout_height" parameters in the xml.
if (getLayoutParams().width > 0 && getLayoutParams().height > 0)
{
getLayoutParams().width = getHeight();
getLayoutParams().height = getWidth();
requestLayout();
}
else
{
// Wait for the layout to be attached, because if this is
// called, it's still not attached. To make sure, get
// width and height first. If they are non-zero, you can
// apply the change. Otherwise, attach a listener.
if (getWidth() > 0 && getHeight() > 0)
{
getLayoutParams().width = getHeight();
getLayoutParams().height = getWidth();
requestLayout();
}
else
{
// This will be called once the view dimensions are set,
// so you can safely use the width and height here.
getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
{
#Override
public boolean onPreDraw()
{
if (getViewTreeObserver().isAlive())
getViewTreeObserver().removeOnPreDrawListener(this);
getLayoutParams().width = getHeight();
getLayoutParams().height = getWidth();
requestLayout();
// Return true here.
return true;
}
});
}
}
}
}
}
It looks like you called init() so early which caused the NullPointerException eventually because your CustomSeekBar object isn't fully constructed. Remember that until the last line of your CustomSeekBar constructor, you cannot call any method such as setProgress() which will internally use the same object that is being created(as this is the case here).
Initially in the constructor you called init() > setProgress() > setProgressDetail() > setSeekBarChange() > setThumb() > updateThumbAndTrackPos() > setThumbPos() > updateGestureExclusionRects() > mGestureExclusionRects.clear() where mGestureExclusionRects is null because it isn't yet initialized.
Note: here ">" means "which in turn calls"
Instead, if you want to set the progress to 0 initially, then create a int variable initialized to 0 and then update it later from your xml to keep track of the progress in your CustomSeekBar view as :
public class CustomSeekBar extends AbsSeekBar {
private int mStartProgress;
public CustomSeekBar(Context context) {
this(context, null);
}
public CustomSeekBar(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.yourSeekBarStyle);
}
public CustomSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public CustomSeekBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
// obtain attribute from xml and set it
final TypedArray a = ........;
mStartProgress = a.getInt(R.styleable.yourSeekBarStyle_startProgress, mStartProgress);
// ........
a.recycle();
}
private void init(){
// do not call method like setProgress() here
// as the object is still in the process of
// being created.
mStartProgress = 0;
}
}
I am have a little trouble understanding the AsyncTask and whether or not i can actually do what i am trying to do.
Within my onCreate method of my activity I am doing a few things, one of which is to create a GLSurfaceView and set my renderer. I want this process to be done by an AsyncTask in the background.
Here is my code
public class ActivityTest extends BaseGameActivity
{
/** Hold a reference to our GLSurfaceView */
private MYGLSurfaceView mGLSurfaceView;
public MYGamePlay GamePlay;
public GoogleApiClient mGoogleApiClient = null;
private AdView adView;
private static final String AD_UNIT_ID = "*******************************";
private Button RotateButton;
private CreateRenderer mCreateRenderer;
private TextView Score;
private RelativeLayout layout;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Dialog loader_dialog = new Dialog(this,android.R.style.Theme_Black_NoTitleBar_Fullscreen);
loader_dialog.setContentView(R.layout.loading_screen);
loader_dialog.show();
// Create an ad.
adView = new AdView(this);
adView.setAdSize(AdSize.SMART_BANNER);
adView.setAdUnitId(AD_UNIT_ID);
// create the layout that holds the combined game layout
layout = new RelativeLayout(this);
layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
// Create an ad request. Check logcat output for the hashed device ID to
// get test ads on a physical device.
AdRequest adRequest = new AdRequest.Builder()
.addTestDevice("***********************").build();
// Start loading the ad in the background.
adView.loadAd(adRequest);
Score = new TextView(this);
Score.setText(" 0");
RelativeLayout.LayoutParams scoreParams = new
RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
Score.setLayoutParams(scoreParams);
Typeface tf = Typeface.createFromAsset(getAssets(),"Fonts/D3Euronism_b.ttf");
Score.setTextSize(getResources().getDimension(R.dimen.textsize));
Score.setTypeface(tf);
Score.setTextColor(Color.parseColor("#FDAA03"));
LayoutInflater inflater = (LayoutInflater) this.getSystemService(this.LAYOUT_INFLATER_SERVICE);
View userInterface = inflater.inflate(R.layout.user_interface, null);
RotateButton = (Button) userInterface.findViewById(R.id.rotbutton);
RotateButton.setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
//irrelivant
}
});
RelativeLayout.LayoutParams adParams =
new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
adParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
adParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
mCreateRenderer = new CreateRenderer(this, Score, mGLSurfaceView);
mCreateRenderer.execute();
layout.addView(userInterface);
layout.addView(Score);
layout.addView(adView, adParams);
setContentView(layout);
}
#Override
protected void onResume()
{
// The activity must call the GL surface view's onResume() on activity onResume().
super.onResume();
//mGLSurfaceView.onResume();
}
#Override
protected void onPause()
{
// The activity must call the GL surface view's onPause() on activity onPause().
super.onPause();
//mGLSurfaceView.onPause();
}
private class CreateRenderer extends AsyncTask<Void, Void, GLSurfaceView>
{
Context baseClassContext;
RBGLSurfaceView myGLSurfaceView;
TextView GameScore;
public CreateRenderer(Context mContext, TextView mScore, RBGLSurfaceView rGLSurfaceView )
{
baseClassContext = mContext;
GameScore = mScore;
myGLSurfaceView = rGLSurfaceView;
}
#Override
protected GLSurfaceView doInBackground(Void... params)
{
final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
final boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000;
if (supportsEs2)
{
// Request an OpenGL ES 2.0 compatible context.
/*line 226*/ myGLSurfaceView = new MYGLSurfaceView(baseClassContext); new GLSurfaceView(baseClassContext);
myGLSurfaceView.setEGLContextClientVersion(2);
final DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
// Set the renderer to our demo renderer, defined below.
mGoogleApiClient = getApiClient();
layout.addView(myGLSurfaceView);
myGLSurfaceView.setRenderer(new MYRenderer(baseClassContext, GameScore, mGoogleApiClient),displayMetrics);
}
else
{
// This is where you could create an OpenGL ES 1.x compatible
// renderer if you wanted to support both ES 1 and ES 2.
}
return myGLSurfaceView;
}
#Override
protected void onPostExecute(GLSurfaceView result)
{
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... values) {}
}
}
I have been reading conflicting things about AsyncTask like whether i can create a contstructor and pass things to it.
Any way it fails on line 226 which i have marked in the code above.
Here is the logCat
09-05 09:29:29.554: E/AndroidRuntime(7585): FATAL EXCEPTION: AsyncTask #2
09-05 09:29:29.554: E/AndroidRuntime(7585): java.lang.RuntimeException: An error occured while executing doInBackground()
09-05 09:29:29.554: E/AndroidRuntime(7585): at android.os.AsyncTask$3.done(AsyncTask.java:299)
09-05 09:29:29.554: E/AndroidRuntime(7585): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
09-05 09:29:29.554: E/AndroidRuntime(7585): at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
09-05 09:29:29.554: E/AndroidRuntime(7585): at java.util.concurrent.FutureTask.run(FutureTask.java:239)
09-05 09:29:29.554: E/AndroidRuntime(7585): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
09-05 09:29:29.554: E/AndroidRuntime(7585): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
09-05 09:29:29.554: E/AndroidRuntime(7585): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
09-05 09:29:29.554: E/AndroidRuntime(7585): at java.lang.Thread.run(Thread.java:856)
09-05 09:29:29.554: E/AndroidRuntime(7585): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
09-05 09:29:29.554: E/AndroidRuntime(7585): at android.os.Handler.<init>(Handler.java:197)
09-05 09:29:29.554: E/AndroidRuntime(7585): at android.os.Handler.<init>(Handler.java:111)
09-05 09:29:29.554: E/AndroidRuntime(7585): at android.view.SurfaceView$1.<init>(SurfaceView.java:122)
09-05 09:29:29.554: E/AndroidRuntime(7585): at android.view.SurfaceView.<init>(SurfaceView.java:122)
09-05 09:29:29.554: E/AndroidRuntime(7585): at android.opengl.GLSurfaceView.<init>(GLSurfaceView.java:213)
09-05 09:29:29.554: E/AndroidRuntime(7585): at com.game.cuberush.MYGLSurfaceView.<init>(MYGLSurfaceView.java:34)
09-05 09:29:29.554: E/AndroidRuntime(7585): at com.game.test.ActivityTest$CreateRenderer.doInBackground(ActivityTest.java:226)
09-05 09:29:29.554: E/AndroidRuntime(7585): at com.game.test.ActivityTest$CreateRenderer.doInBackground(ActivityTest.java:1)
09-05 09:29:29.554: E/AndroidRuntime(7585): at android.os.AsyncTask$2.call(AsyncTask.java:287)
09-05 09:29:29.554: E/AndroidRuntime(7585): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
09-05 09:29:29.554: E/AndroidRuntime(7585): ... 4 more
this is the first time i have tried to use AsyncTask so i realise i am probably making a mess with it. So any help with this would be great
EDIT method using annotations still produces the same result the code a put the #Background annotation doesnt seem to be running on a seperate thread as the oncreate is still waiting for it, unless i am doing it wrong
called un onCreate
CreateRender(mGLSurfaceView, this, Score, loader_dialog, mGoogleApiClient, displayMetrics);
method CreateRender
#Background
protected void CreateRender(MYGLSurfaceView myGLSurfaceView, Context mContext, TextView mScore, Dialog mDialog, GoogleApiClient gAPI, DisplayMetrics mDispMet )
{
myGLSurfaceView.setRenderer(new MYRenderer(mContext, mScore, mDialog, gAPI),mDispMet);
mGLSurfaceView = returnResult(myGLSurfaceView);
}
#UiThread
MYGLSurfaceView returnResult(MYGLSurfaceView res)
{
return res;
}
this must be wrong
If you get crazy using AsyncTask i prefer to try AndroidAnnotations. Instead of writing a complete class to handle your background tasks, you just use a #Background annotation over your method. This concept saves a lot of code and it works!
This is an example from the android annotations wiki at github:
#EActivity(R.layout.translate) // Sets content view to R.layout.translate
public class TranslateActivity extends Activity {
#ViewById // Injects R.id.textInput
EditText textInput;
#ViewById(R.id.myTextView) // Injects R.id.myTextView
TextView result;
#AnimationRes // Injects android.R.anim.fade_in
Animation fadeIn;
#Click // When R.id.doTranslate button is clicked
void doTranslate() {
translateInBackground(textInput.getText().toString());
}
#Background // Executed in a background thread
void translateInBackground(String textToTranslate) {
String translatedText = callGoogleTranslate(textToTranslate);
showResult(translatedText);
}
#UiThread // Executed in the ui thread
void showResult(String translatedText) {
result.setText(translatedText);
result.startAnimation(fadeIn);
}
// [...]
}
Ive been wrestling with AsyncTask the last couple of days myself. It seems to have some kind of an aversion to surfaces.
I would suggest a change of approach -- create the view in onCreate/onResume ( depending on your needs ) and avoid tying in nonexistent surfaces with AsyncTask.
This approach worked for me, hope it does for you as well!
Your basic problem is that you try to change the UI from a non-ui thread. From the documentation:
Additionally, the Andoid UI toolkit is not thread-safe. So, you must not manipulate your UI from a worker thread—you must do all manipulation to your user interface from the UI thread.
Asynctask is actually a convience for that. It does some background work off the main thread and then runs the onPostExecute() on the ui-thread. That means 2 things: first you can change the ui in onPostExecute() and everything done here will be executed serial to the ui (so it could be blocked)
There is the usual quickfix for that with
activity.runOnUiThread(new Runnable() {
public void run() {
//this will be executed on the ui thread
}
});
which will not help you since it will then block the ui again. Im actually not sure if you can do what you want, since some things just can be done in the background (e.g. inflating a real complex xml in onCreateView()). You could try to create your own looper like:
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
and handle your surfaceview there, but Im not sure that works.
Further resouces:
Run SurfaceView off UI Thread
Can't create handler inside thread that has not called Looper.prepare()
What I'm trying do to is using a custom CursorAdapter, in order to choose which layout to show and also to populate View items such as TextViews and also ImageView.
Now not in all the listview items there gonna be an image.
My CursorAdapter code is -
private static class ViewHolder {
TextView mesg;
TextView mesg2;
TextView send;
ImageView myImage;
}
public class ChatCursorAdapter extends CursorAdapter implements OnClickListener {
public ChatCursorAdapter(Context context, Cursor c) {
super(context, c, 0);
}
#Override
public int getCount() {
return getCursor() == null ? 0 : super.getCount();
}
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getItemViewType(int _position) {
Cursor cursor = (Cursor) getItem(_position);
return getItemViewType(cursor);
}
private int getItemViewType(Cursor cursor) {
String sender = cursor.getString(2);
String saveUser = user;
if (saveUser.equalsIgnoreCase(sender)){
return 0;
}else{
return 1;
}
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = (ViewHolder) view.getTag();
String msg = cursor.getString(3);
String msg2 = cursor.getString(4);
String sender = cursor.getString(2);
holder.mesg.setText(getSmiledText(Main.this,msg));
holder.mesg2.setText(getSmiledText(Main.this,msg2));
holder.send.setText(sender);
picPath = cursor.getString(8);
if(picPath == null || picPath.isEmpty()){
holder.myImage.setVisibility(View.GONE);
}else{
File file = new File(picPath);
if(file.exists()){
new AsyncImageSetter(holder.myImage, picPath).execute();
holder.myImage.setOnClickListener(this);
}
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
ViewHolder holder = new ViewHolder();
View itemLayout = null;
switch(getItemViewType(cursor)){
case 0:
itemLayout = getLayoutInflater().inflate(R.layout.msg_item1,parent, false);
break;
case 1:
itemLayout = getLayoutInflater().inflate(R.layout.msg_item13, parent,false);
break;
}
itemLayout.setTag(holder);
holder.mesg = (TextView) itemLayout.findViewById(R.id.text_start);
holder.mesg2 = (TextView) itemLayout.findViewById(R.id.text_end);
holder.send = (TextView) itemLayout.findViewById(R.id.text_from);
holder.myImage = (ImageView) itemLayout.findViewById(R.id.imageView_msgpic);
return itemLayout;
}
}
As you can see when there a need to load an image to the ImageView, I'm using asynctask in order to let the flow of the list view scrolling to be much more smoother.
This how the asynctask code is -
public class AsyncImageSetter extends AsyncTask<Void, Void, Void> {
private ImageView img;
private String path;
private Bitmap bm;
public AsyncImageSetter(ImageView img, String path) {
this.img = img;
this.path = path;
}
#Override
protected Void doInBackground(Void... params) {
bm = BitmapFactory.decodeFile(path);
bm = setImageToImageView(path);
return null;
}
#Override
protected void onPostExecute(Void result) {
img.setTag(path);
img.setImageBitmap(bm);
//img.setVisibility(View.VISIBLE);
super.onPostExecute(result);
}
}
Well the thing is that it sure made the scrolling alot more smoother, but it seems to make the app crash a lot of times.
The logcat says the next -
03-24 17:07:34.125: E/AndroidRuntime(15422): FATAL EXCEPTION: AsyncTask #2
03-24 17:07:34.125: E/AndroidRuntime(15422): java.lang.RuntimeException: An error occured while executing doInBackground()
03-24 17:07:34.125: E/AndroidRuntime(15422): at android.os.AsyncTask$3.done(AsyncTask.java:299)
03-24 17:07:34.125: E/AndroidRuntime(15422): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
03-24 17:07:34.125: E/AndroidRuntime(15422): at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
03-24 17:07:34.125: E/AndroidRuntime(15422): at java.util.concurrent.FutureTask.run(FutureTask.java:239)
03-24 17:07:34.125: E/AndroidRuntime(15422): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
03-24 17:07:34.125: E/AndroidRuntime(15422): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
03-24 17:07:34.125: E/AndroidRuntime(15422): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
03-24 17:07:34.125: E/AndroidRuntime(15422): at java.lang.Thread.run(Thread.java:841)
03-24 17:07:34.125: E/AndroidRuntime(15422): Caused by: java.lang.OutOfMemoryError
03-24 17:07:34.125: E/AndroidRuntime(15422): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
03-24 17:07:34.125: E/AndroidRuntime(15422): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:623)
03-24 17:07:34.125: E/AndroidRuntime(15422): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:378)
03-24 17:07:34.125: E/AndroidRuntime(15422): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:417)
03-24 17:07:34.125: E/AndroidRuntime(15422): at at.vcity.androidim.MainChat$AsyncImageSetter.doInBackground(MainChat.java:3356)
03-24 17:07:34.125: E/AndroidRuntime(15422): at at.vcity.androidim.MainChat$AsyncImageSetter.doInBackground(MainChat.java:1)
03-24 17:07:34.125: E/AndroidRuntime(15422): at android.os.AsyncTask$2.call(AsyncTask.java:287)
03-24 17:07:34.125: E/AndroidRuntime(15422): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
03-24 17:07:34.125: E/AndroidRuntime(15422): ... 4 more
So what am I doing wrong here?
Thanks for any kind of help
It looks to me like the Bitmap you are trying to store in memory is too large to be stored in your tablet/emulator's memory. Here;
bm = BitmapFactory.decodeFile(path);
See if the code works with a much smaller file than the one that is coming from your current path (also see if it works with a smaller list). This could also be an instance of 'The straw that broke the camel's back'. If your current application is already very memory intensive you might have to go through your current code and optimise for memory management.
Because your are creating an AsyncTask for each item in the ListView, your trying to hold that many images in memory at once. So you might need to find another way to do it. You might need to try loading the image's thumbnail into your ImageViews instead.
An example of getting an images thumbnail.
I hope this helps.
An Example Implementation
Just to run through a potential way to implement the above linked thumbnail example, what I might do to get the thumbnail is I could store the context passed to your ChatCursorAdapter by adding the following as a class variable (and instantiate it in the constructor);
Context ourContext;
public ChatCursorAdapter(Context context, Cursor c) {
super(context, c, 0);
ourContext = context;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
...
new AsyncImageSetter(holder.myImage, picPath, ourContext.getContentResolver()).execute();
...
}
Then (as above) I might use the Context to get the ContentResolver instance and pass that instance into your AsyncTask via it's constructor. Then we could add the method in the example code to get the thumbnail into the custom AsyncTask, which might look something like this;
ContentResolver cr;
public AsyncImageSetter(ImageView img, String path, ContentResolver cr) {
this.img = img;
this.path = path;
this.cr = cr;
}
...
#Override
protected Void doInBackground(Void... params) {
try{
bm = getThumbnail(cr, path);
}catch(Exception e){}
return null;
}
private Bitmap getThumbnail(ContentResolver cr, String path) throws Exception {
Cursor ca = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[] { MediaStore.MediaColumns._ID }, MediaStore.MediaColumns.DATA + "=?", new String[] {path}, null);
if (ca != null && ca.moveToFirst()) {
int id = ca.getInt(ca.getColumnIndex(MediaStore.MediaColumns._ID));
ca.close();
return MediaStore.Images.Thumbnails.getThumbnail(cr, id, MediaStore.Images.Thumbnails.MICRO_KIND, null );
}
ca.close();
return null;
}
The cause is in your stacktrace: java.lang.OutOfMemoryError. It looks like one of two things -- either your images are too large or you are leaking memory (or both).
My recommendation would be to use one of the several libraries for doing background image loading. Here are a couple of suggestions:
https://github.com/nostra13/Android-Universal-Image-Loader
https://github.com/square/picasso
I'm trying to make a simple audio delay effect by creating a number of threads. Each thread instantiates a SoundPool object and thus plays a copy the sound. The delay effect is obtained by using Thread.sleep(delayTime), where delayTime is conveniently setted at a different value for each thread, in order to delay the sound reproduction. I'm storing the created SoundPool objects into an array in order to manipulate them later (e.g. changing some parameter value).
I've tried to implement the threads in both ways (as a simple Thread or implementing Runnable), and both implementations present issues in accessing the SoundPool objects once they've been setted by the threads, which are presumably due to the locking of the object by its creating thread. The issues don't seem to occur when sharing a simple variable, though.
Simply put, I want to access publicly to an object which has been manipulated by a thread, and I don't know how to release the thread's lock over it.
Here's the code.
FIRST IMPLEMENTATION
The first implementation successfully creates the effect, but the SoundPool objects aren't accessible from outside the threads. For example I created a button whose click shoud pause the playing of all the sound copies.
public class MainActivity extends Activity implements OnClickListener {
public SoundPool soundCopies[];
int soundCopiesNumber = 6;
double delayTimes[];
double volumes[];
int soundIds[];
int streamIds[];
int copyIndex = 0;
long delayTime = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
//other code
final SoundPool[] soundCopies = new SoundPool[6];
final int[] soundIds = new int[6];
final int[] streamIds = new int[6];
final double[] volumes = new double[6];
double[] delayTimes = new double[6];
//filling volumes[] and delayTimes[] with convenient values and other code
//create a thread for each sound copy
for (int i = 0; i<soundCopiesNumber; i++ ){
copyIndex = i;
delayTime = (long)delayTimes[i];
new Thread(){
public void run(){
try {
Thread.sleep(delayTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
//create a SoundPool
soundCopies[copyIndex] = new SoundPool(6, AudioManager.STREAM_MUSIC, 0);
//other code related to the SoundPool managament, setting parameters
//such as volume and playing the sound
}.start();
}
//managing the button click in order to stop playing
#Override
public void onClick(View arg0) {
switch (arg0.getId()) {
//other code
case R.id.delayStop:
for (int i = 0; i<soundCopiesNumber; i++ ){
try {
//pause the playing of each sound
soundCopies[i].pause(streamIds[i]);
} catch (Exception e){
e.printStackTrace();
}
}
break;
default:
break;
}
}
}
The exception generated by clicking the button is:
W/System.err(31075): java.lang.NullPointerException
W/System.err(31075): at com.example.soundpooltest.MainActivity.onClick(MainActivity.java:174)
W/System.err(31075): at android.view.View.performClick(View.java:4424)
W/System.err(31075): at android.view.View$PerformClick.run(View.java:18383)
W/System.err(31075): at android.os.Handler.handleCallback(Handler.java:733)
W/System.err(31075): at android.os.Handler.dispatchMessage(Handler.java:95)
W/System.err(31075): at android.os.Looper.loop(Looper.java:137)
W/System.err(31075): at android.app.ActivityThread.main(ActivityThread.java:4998)
W/System.err(31075): at java.lang.reflect.Method.invokeNative(Native Method)
W/System.err(31075): at java.lang.reflect.Method.invoke(Method.java:515)
W/System.err(31075): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777)
W/System.err(31075): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593)
W/System.err(31075): at dalvik.system.NativeStart.main(Native Method)
SECOND IMPLEMENTATION The second implementation uses Runnable to create an array of threads, but they don't even access the soundCopies array which is instantiated in the onCreate method (that is, on the main thread). If my first implementation is unviable for my purposes I will post that code too.
Thanks in advance.
I'm trying to create my first Android App (a game) but I'm having some difficulties getting started.
When I run my code I get this error log:
05-25 02:41:51.022: WARN/dalvikvm(634): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
05-25 02:41:51.040: ERROR/AndroidRuntime(634): FATAL EXCEPTION: main
05-25 02:41:51.040: ERROR/AndroidRuntime(634): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.stickfigs.nmg/com.stickfigs.nmg.NMG}: java.lang.NullPointerException
05-25 02:41:51.040: ERROR/AndroidRuntime(634): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663)
05-25 02:41:51.040: ERROR/AndroidRuntime(634): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
05-25 02:41:51.040: ERROR/AndroidRuntime(634): at android.app.ActivityThread.access$2300(ActivityThread.java:125)
05-25 02:41:51.040: ERROR/AndroidRuntime(634): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
05-25 02:41:51.040: ERROR/AndroidRuntime(634): at android.os.Handler.dispatchMessage(Handler.java:99)
05-25 02:41:51.040: ERROR/AndroidRuntime(634): at android.os.Looper.loop(Looper.java:123)
05-25 02:41:51.040: ERROR/AndroidRuntime(634): at android.app.ActivityThread.main(ActivityThread.java:4627)
05-25 02:41:51.040: ERROR/AndroidRuntime(634): at java.lang.reflect.Method.invokeNative(Native Method)
05-25 02:41:51.040: ERROR/AndroidRuntime(634): at java.lang.reflect.Method.invoke(Method.java:521)
05-25 02:41:51.040: ERROR/AndroidRuntime(634): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
05-25 02:41:51.040: ERROR/AndroidRuntime(634): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
05-25 02:41:51.040: ERROR/AndroidRuntime(634): at dalvik.system.NativeStart.main(Native Method)
05-25 02:41:51.040: ERROR/AndroidRuntime(634): Caused by: java.lang.NullPointerException
05-25 02:41:51.040: ERROR/AndroidRuntime(634): at com.stickfigs.nmg.NMG.onCreate(NMG.java:32)
05-25 02:41:51.040: ERROR/AndroidRuntime(634): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
05-25 02:41:51.040: ERROR/AndroidRuntime(634): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
05-25 02:41:51.040: ERROR/AndroidRuntime(634): ... 11 more
05-25 02:41:51.062: WARN/ActivityManager(59): Force finishing activity com.stickfigs.nmg/.NMG
I think the problem is this "thread exiting with uncaught exception" part, I have no idea what the exception could be or what's causing it.
Here is my code:
NMGView.java:
package com.stickfigs.NMG;
import android.content.Context;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
class NMGView extends SurfaceView implements SurfaceHolder.Callback {
class NMGThread extends Thread {
//State-tracking constants
public static final int STATE_LOSE = 1;
public static final int STATE_PAUSE = 2;
public static final int STATE_READY = 3;
public static final int STATE_RUNNING = 4;
public static final int STATE_WIN = 5;
/** The state of the game. One of READY, RUNNING, PAUSE, LOSE, or WIN */
private int mode;
/** Handle to the surface manager object we interact with */
private SurfaceHolder surfaceHolder;
public NMGThread(SurfaceHolder surfaceHolderc, Context contextc) {
// get handles to some important objects
surfaceHolder = surfaceHolderc;
context = contextc;
}
/**
* Restores game state from the indicated Bundle. Typically called when
* the Activity is being restored after having been previously
* destroyed.
*
* #param savedState Bundle containing the game state
*/
public synchronized void restoreState(Bundle savedState) {
synchronized (surfaceHolder) {
setState(STATE_PAUSE);
}
}
/**
* Sets the game mode. That is, whether we are running, paused, in the
* failure state, in the victory state, etc.
*
* #param mode one of the STATE_* constants
* #param message string to add to screen or null
*/
public void setState(int modec) {
synchronized (surfaceHolder) {
mode = modec;
}
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
/** Handle to the application context, used to e.g. fetch Drawables. */
private Context context;
/** The thread that actually draws the animation */
private NMGThread thread;
public NMGView(Context context, AttributeSet attrs) {
super(context, attrs);
// register our interest in hearing about changes to our surface
SurfaceHolder holder = getHolder();
holder.addCallback(this);
// create thread only; it's started in surfaceCreated()
thread = new NMGThread(holder, context);
setFocusable(true); // make sure we get key events
}
/**
* Fetches the animation thread corresponding to this LunarView.
*
* #return the animation thread
*/
public NMGThread getThread() {
return thread;
}
}
NMG.java:
package com.stickfigs.nmg;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import com.stickfigs.nmg.NMGView.NMGThread;
public class NMG extends Activity {
/** Called when the activity is first created. */
/** A handle to the thread that's actually running the animation. */
private NMGThread nMGThread;
/** A handle to the View in which the game is running. */
private NMGView nMGView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Turn off the window's title bar
// TODO Turn off the status bar
requestWindowFeature(Window.FEATURE_NO_TITLE);
// tell system to use the layout defined in our XML file
setContentView(R.layout.nmg_layout);
// get handles to the LunarView from XML, and its LunarThread
nMGView = (NMGView) findViewById(R.id.nmg);
nMGThread = nMGView.getThread();
if (savedInstanceState == null) {
// we were just launched: set up a new game
nMGThread.setState(NMGThread.STATE_READY);
Log.w(this.getClass().getName(), "SIS is null");
} else {
// we are being restored: resume a previous game
nMGThread.restoreState(savedInstanceState);
Log.w(this.getClass().getName(), "SIS is nonnull");
}
}
}
UPDATE: Here is my R.java and nmg_layout.xml:
R.java:
package com.stickfigs.nmg;
public final class R {
public static final class attr {
}
public static final class drawable {
public static final int icon=0x7f020000;
}
public static final class id {
public static final int nmg=0x7f050000;
}
public static final class layout {
public static final int nmg_layout=0x7f030000;
}
public static final class string {
public static final int app_name=0x7f040001;
public static final int hello=0x7f040000;
}
}
nmg_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.stickfigs.nmg.NMGView
android:id="#+id/nmg"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</FrameLayout>
If you look through the stack trace, you will see a "Caused by..." line (sometimes more than one). The last one of those is the important one. It says that there was a null pointer exception on line 32 of NMG.java. That line, and the line before it, are:
nMGView = (NMGView) findViewById(R.id.nmg);
nMGThread = nMGView.getThread();
Evidently, no view with id R.id.nmg is in layout R.layout.nmg_layout. That's what's causing your problem.
In your XML file, the R.id.nmg do exist.
So I think the problem is caused by inflating the NMGView object from the resource.
You should examine your NMGView source code, especially in its constructor.
If you are using "multiDexEnabled true" in your "build.gradle(Module:app)" , remove this line from "defaultConfig" and sync project.
It works in my case !!!
This problems happens because most of the time the SurfaceView onDraw() method is running when you destroy the surfaceView then you get a NULL POINTER ERROR because the canvas doesn´t exist by that moment. I have fixed this problem catching all the drawing stuff with the NullPointerException:
#Override
public void onDraw(Canvas canvas) {
try {
//Drawing Stuff
}catch(NullPointerException e){
Log.e("NULL POINTER EXCEPTION","Canvas NULL POINTER");
}
}
If you implement onPause(), onDestroy() methods in your Main activity you will get the following order: first: E/onPause﹕ ON PAUSE --> next E/surfaceDestroyed﹕ SURFACE DESTROYED --> E/NULL POINTER EXCEPTION﹕ Canvas NULL POINTER --> finally
E/onDestroy﹕ ON DESTROY
this is surfaceDestroyed method I am using:
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
Log.e("surfaceDestroyed", "SURFACE DESTROYED ");
thread.setRunning(false);
try {
//thread.setRunning(false);
thread.join();
} catch (InterruptedException e) {
Log.e("Surface Thread Stopped","SURFACE THREAD STOPPED");
}
}