accessing objects from multiple threads - java

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.

Related

Cannot Update Image from Runnable - Android

I have the following class that implements runnable. When I start the thread I get an error preventing me from updating the image. I have tried setting the image as you will see in the runOnUiThread function but it doesn't work. I would like to ultimately update the image every x seconds but I cannot seem to do this unless I put the thread inside the main activity class. Once I move it out nothing I try works.
public class Test implements Runnable {
MainActivity activity;
ArrayList<Media> media = new ArrayList<Media>();
public Test(MainActivity activity){
this.activity = activity;
}
public void run(){
activity.runOnUiThread(new Runnable(){
#Override
public void run() {
ImageView img= (ImageView) activity.findViewById(R.id.imageView1);
img.setImageResource(R.drawable.ic_launcher_foreground);
}
});
}
}
In MainActivity.java's onCreate() function I start the thread.
Test p = new Test(this);
Thread t = new Thread(p);
t.start();
Then my error:
2019-10-31 19:26:47.274 5407-5407/com.desotomatrix.digitalsignageplayer E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.desotomatrix.digitalsignageplayer, PID: 5407
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageView.setImageResource(int)' on a null object reference
at com.desotomatrix.digitalsignageplayer.Test$1.run(Test.java:30)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:209)
at android.app.ActivityThread.main(ActivityThread.java:7021)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:486)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:872)

Cannot get next song to play after onCompleteListener

I have read numerous different responses on this matter but I just wanted to clarify one thing about the onCompletionListener method for MediaPlayer. I have a configuration that is currently working and playing a song after it completes the first one, but after the second one ends it will not play another song from the array. It will also not display the metadata for the new track either. My guess is that the onCompletionListener only runs once and doesn't transfer to the newly created MediaPlayer instance. More Specifically the answer I'm looking for is can the onCompleteListener run more than once? Or is it a non looping function?
Video demonstrating the issue: https://youtu.be/WXDtCktTh3M
Here is what I have for my listener block:
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer arg0) {
if (chosenPath == null) {
seekBar.setProgress(0);
mediaPlayer.seekTo(0);
} else {
songOrderCounter += 1;
System.out.println("SONG_ITERATOR_COUNT: " + songOrderCounter);
try {
/*handler.removeCallbacks(moveSeekBarThread);
songUpdateTimeHandler.removeCallbacks(updateSongTime);*/
Log.d("PATH_WORKING", allMusicFiles[songOrderCounter].toString());
mediaPlayer.stop();
mediaPlayer.reset();
mediaPlayer.release();
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(allMusicFiles[songOrderCounter].toString());
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
metaRetriever();
seekBar.setProgress(0);
seekBar.setMax(mediaPlayer.getDuration());
trackTime();
}
});
mediaPlayer.prepareAsync();
metaRetriever(); /* Moved inside onPrepared*/
} catch (Exception e) {
System.out.println("NEXT_SONG_FAILED: " + e);
}
}
}
});
UPDATE
The reason this is not working is because I have created a new MediaPlayer Instance in the onCompletion() function so the listener will not associate with the newly created MediaPlayer instance. Therefore it will not listen for the completion of the newly created MediaPlayer. I removed the new MediaPlayer section of code from the setOnCompleteListener() function and now there are issues with the runnable threads that are keeping track of seekbar and time progress causing it to crash when it reaches the end of the file
D/PATH_WORKING: /storage/emulated/0/Music/01 Control.mp3
I/System.out: NEXT_SONG_FAILED: java.lang.IllegalStateException
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.macyg.androidmediaplayer, PID: 12784
java.lang.IllegalStateException
at android.media.MediaPlayer.getCurrentPosition(Native Method)
at com.example.macyg.androidmediaplayer.MainActivity$12.run(MainActivity.java:596)
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:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
And the Runnable causing the crash:
private Runnable moveSeekBarThread = new Runnable() {
public void run() {
if(mediaPlayer.getCurrentPosition() <= mediaPlayer.getDuration()) {
int mediaPos_new = mediaPlayer.getCurrentPosition();
int mediaMax_new = mediaPlayer.getDuration();
seekBar.setMax(mediaMax_new);
seekBar.setProgress(mediaPos_new);
handler.postDelayed(this, 100); //Looping the thread after 0.3 second
// seconds
}else{}
}
};

Android Game development E/JavaBinder: FAILED BINDER TRANSACTION

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;
}
}
}

java.lang.IllegalStateException in MediaPlayer

This is my code:
final MediaPlayer[] threeSound = new MediaPlayer[1];
threeSound[0] = new MediaPlayer();
final CountDownTimer playThreeSound = new CountDownTimer(1000, 1) {
boolean timerStarted = false;
#Override
public void onTick(long millisUntilFinished) {
torgText.setText("3...");
if (!timerStarted) {
timerStarted = true;
threeSound[0] = MediaPlayer.create(PlayActivity.this, R.raw.three);
try {
threeSound[0].prepare();
threeSound[0].start();
} catch (IOException e) {
e.printStackTrace();
Log.e("IOE", "Something went wrong");
}
}
}
#Override
public void onFinish() {
if (threeSound[0].isPlaying()) {
threeSound[0].stop();
}
playTwoSound.start();
}
};
It throws IllegalStateException. These are logs:
FATAL EXCEPTION: main
Process: testapplication.android.com.guesstune_v2, PID: 3641
java.lang.IllegalStateException
at android.media.MediaPlayer._prepare(Native Method)
at android.media.MediaPlayer.prepare(MediaPlayer.java:1351)
at testapplication.android.com.guesstune_v2.PlayActivity$6.onTick(PlayActivity.java:316)
at android.os.CountDownTimer$1.handleMessage(CountDownTimer.java:133)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:7007)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
What is wrong with preparing MediaPlayer? What should I add to the code? I'm a newbie, sorry for a probably stupid question and for bad English.
The documentation for MediaPlayer states:
MediaPlayer create (Context context, int resid)
Convenience method to create a MediaPlayer for a given resource id. On success, prepare() will already have been called and must not be called again.
https://developer.android.com/reference/android/media/MediaPlayer.html#create(android.content.Context, int)
So your IllegalStateException occurs because prepare() requires the MediaPlayer to be in either a Initialized or Stopped state, but when create(Context context, int resid) is invoked, it calls prepare() resulting in the MediaPlayer being in the Prepared state which it must not be when prepare() is invoked.
In short: remove the prepare() call and the IllegalStateException should no longer occur.
A full State Diagram and list of valid states is presented in the documentation.

java.lang.IllegalStateException: AssetManager has been finalized

I went to sleep yesterday with my app working and today when I tried to run it won't start at all. As soon as I try to open it crashes with a java.lang.IllegalStateException. I've gone several commits back in my code just to rule out it was something I did recently and still. This makes no sense, how can an app just stop working over night? I've looked for the error in the internet and there is not a lot of useful information about it. Is this really an odd error?
Here's the complete stack trace:
E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.IllegalStateException: AssetManager has been finalized!
at android.os.Parcel.readException(Parcel.java:1439)
at android.os.Parcel.readException(Parcel.java:1385)
at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:1947)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1419)
at android.app.Activity.startActivityForResult(Activity.java:3390)
at android.app.Activity.startActivity(Activity.java:3583)
at com.android.launcher2.Launcher.startActivity(Launcher.java:2442)
at com.android.launcher2.Launcher.startActivitySafely(Launcher.java:2469)
at com.android.launcher2.AppsCustomizePagedView.onClick(AppsCustomizePagedView.java:584)
at android.view.View.performClick(View.java:4240)
at android.view.View$PerformClick.run(View.java:17721)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5136)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Since like I said it doesn't seem to be anything that I did I'm not sure what code to post. But given that the app crashes on start here's the code for the two main classes that are supposed to start first:
App
public class App extends Application {
private static App instance;
private static final String TAG = "Starter";
#Override
public void onCreate() {
super.onCreate();
instance = this;
// Enable Local Datastore.
Parse.enableLocalDatastore(this);
//TODO: Register subclasses
// ParseObject.registerSubclass(Challenge.class);
//Parse server
Log.d(TAG, "Initializing Parse");
Parse.initialize(new Parse.Configuration.Builder(this)
.applicationId(getString(R.string.parse_app_id))
.clientKey(getString(R.string.parse_client_key))
.server(getString(R.string.server_address)).build()
);
//Facebook
if (AccessToken.getCurrentAccessToken() == null)
ParseFacebookUtils.initialize(this);
ParseUser.enableAutomaticUser();
ParseACL defaultACL = new ParseACL();
// Optionally enable public read access.
defaultACL.setPublicReadAccess(true);
defaultACL.setPublicWriteAccess(true);
ParseACL.setDefaultACL(defaultACL, true);
Log.d(TAG, "Parse ready");
}
public static App getInstance(){
return instance;
}
}
SplashActivity
public class SplashActivity extends AppCompatActivity {
private static final String TAG = "Splash";
private boolean firstTime = true;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Hide title bar
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_splash);
firstTime = getSharedPreferences(Constants.GENERAL_SHARED_PREFS, MODE_PRIVATE)
.getBoolean(Constants.FIRSTTIME, true);
if (isLoggedIn())
if (firstTime)
startActivity(new Intent(SplashActivity.this, FirstTimeActivity.class));
else
startActivity(new Intent(SplashActivity.this, MenuActivity.class));
else {
Log.d(TAG, "Calling Home");
startActivity(new Intent(SplashActivity.this, WelcomeActivity.class));
finish();
}
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onDestroy() {
super.onDestroy();
}
public boolean isLoggedIn() {
AccessToken accessToken = AccessToken.getCurrentAccessToken();
String parseSession = ParseUser.getCurrentUser().getSessionToken();
return parseSession != null;
}
}
Your stacktrace links to this class in the AOSP.
I think this crash has nothing to do with your app, but as an error in the Launcher class. Try installing from USB debugging and see if that works.
But there are still some details that are blurry. These lines are (from bottom of the stacktrace to the top) the lines that cause problems in com.android.launcher2 package:
https://android.googlesource.com/platform/packages/apps/Launcher2/+/android-4.2.2_r1/src/com/android/launcher2/AppsCustomizePagedView.java#584
https://android.googlesource.com/platform/packages/apps/Launcher2/+/master/src/com/android/launcher2/Launcher.java#2469
https://android.googlesource.com/platform/packages/apps/Launcher2/+/master/src/com/android/launcher2/Launcher.java#2442
From this error, I assume you are using a Nexus or Pixel (or any device with the unaltered source code, meaning stock android.).
From what I can tell from this error, this is not an error related to your app. It appears to be an issue with the launcher you are using. Try installing from USB debugging, or change launcher, and see if that works. Try rebooting your device as well.
Further, from what I see of your code, there are no parcelable classes in use
This error can also be caused when Instant Run loses connection with the Android Emulator as a result of which new app changes are not persisted in the emulator.
Running the app again will solve the issue.

Categories