J2me application out of memory exception on multiple time file play - java

In my j2me application i have to play a small sound file each times user click on an item. But the issues is when i play sound file multiple times like after 10-14 times it gives me
out of memory exception. Although i release the player each time i play the file but still it
gives out of memory exception : Here is the code snippet,
public void playSound(String soundFile) {
try{
if (player!=null) {
try {
player.deallocate(); //deallocate the unnecessary memory.
} catch (Exception ex) {
player=null;
System.gc();
}
}
player = Manager.createPlayer(getClass().getResourceAsStream(musicFolder + soundFile), "audio/mpeg");
// player = Manager.createPlayer(is, "audio/mpeg");
player.realize();
// get volume control for player and set volume to max
VolumeControl vc = (VolumeControl) player.getControl("VolumeControl");
if (vc != null) {
vc.setLevel(100);
}
player.prefetch();
player.start();
isException=false;
} catch (Exception e) {
isException=true;
}
}
Can someone tell me what is going wrong?

3 things to keep in mind
If you are going to play the same sound several times, you might want to keep one Player prefetched and simply start it multiple times.
When you want to properly cleanup a player, you should call Player.close()
You may want to use a media event listener to close and/or restart a player independently of user input.

I think you should also call
player.close()
right after after
player.deallocate();
According to documentation "When deallocate returns, the Player is in the UNREALIZED or REALIZED state." but close goes further... "When the method returns, the Player is in the CLOSED state and can no longer be used."

I'm not sure why the de-allocation isn't working. I guess it either takes longer to de-allocated than to create a new one, or the de-allocation fails for some reason. Is there a player.stop() to match the player.start()?
Another thing to try (if nothing else, for good form :) is not to create new player unless you need to/should. I.e. move the
if(player!=null){
So it also covers
player = Manager.createPlayer(getClass().getResourceAsStream(musicFolder + soundFile), "audio/mpeg");
HTH!

Related

Android - Saving data to an internal storage

I'm working on a simple to-do list app, and I'm trying to read/write data from/to internal storage. I'm trying to understand when exactly those read/write methods should be called.
I know that the activity class has an onCreate() method which will be a reasonable location for my read method, but where should I call my write method?
I want to call it when the app closes/ends, so I'd assume onDestory() is a good location, but i heard that onDestroy() may not be a good location for data storage operations and i should use onStop().
Any help or ideas?
It depends on Application Lifecycle.
And see This.
onStop() invokes when user press home button(Hard Key).
And then, if memory insufficient or another reason, Android Memory Manager will kill your app instant and onDestory() will never called.
The best thing you have to is make a button to save datas. Of course, Include onStop() save routine.
Following the table in the Android Developers Guide on the Activity Lifecycle, your app may be killed by the system any time without warning after either onPause() (for Pre-HONEYCOMB devices) or after onStop(). So you probably want to write your data in these methods to make sure nothing gets lost. So for newer devices (API level 11 and up), onStop() should be fine. If your app should run on older devices as well, onPause() would be the best place.
This is Just sample code. But you get the idea. Create a custom method implementing the code below and call it on some events like "onClick" or any other.
File file;
FileOutputStream strem = null;
String line = "Hey this is my name";
try {
file = new File("sdcard/newFile.txt");
strem = new FileOutputStream(file);
byte[] bytes = line.getBytes();
strem.write(bytes);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
strem.close();
} catch (IOException e) {
e.printStackTrace();
}
}

Save serializable object in persistent storage (android)

I need to store a complex custom object in persistent storage in order to save the user's game progress in my app. The object and every object within this object implements Serializable
I call the use the loading and saving methods to pass the object between activities. I also call the Save method onStop() to save the object when the app is closed/destroyed. It works fine.
public static Game Load(Context context){
try{
FileInputStream fis = context.openFileInput("player1.data");
ObjectInputStream is = new ObjectInputStream(fis);
Game game = (Game) is.readObject();
is.close();
fis.close();
return game;
}catch (Exception e){
Log.e("#Load", "creating new game - \n" + e.toString());
Game newGame = new Game();
return newGame;
}
}
public static void Save(Context context,Game game){
try{
FileOutputStream fos = context.getApplicationContext().openFileOutput("player1.data", Context.MODE_PRIVATE);
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(game);
os.close();
fos.close();
}catch (Exception e){
Log.e("#Save", "Failed to save - \n" + e.toString());
}
}
However, if the app is Force Closed or closed and destroyed, the Game object gets messed up. When relaunched, the application will load the game that was saved onStop(), but when the game object is changed/interacted with by the user through the application, my app force closes with the "has stopped unexpectedly" display message on the phone screen. From looking at the log, i know that when the Game object is being loaded on launch after being Force Closed / Destroyed, the Load method is returning game rather than newGame, so somehow the saving/loading process in between the Force Close messes something up.
On the log, I see this:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference
So, I am led to believe that something strange is going on with using Serializable, or I am incorrectly writing to persistent storage.
My questions: Do you see anything fundamentally wrong with my code? (keep in mind that this code does work, it just doesn't work under the Force Close circumstance)
I have been told to look into using gson/JSON (?) for my purposes; will this method have better results than Serializable and how can I use this?
Update: It seems that when Force Stop occurs, no methods are called - including the onDestroy() and onStop(). If this is the case, then why is my app not returning newGame? Looking at the log while Force Closing, a message that said something about "onSavedInstance not called," what is this?
I am getting the feeling that I should avoid Serializable entirely...
onCreate snippet
Game game;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
game = LoadGame.Load(this); //LoadGame is the class which contains Save,Load methods
#Override
protected void onStop() {
LoadGame.Save(this,game);
super.onStop();
}
Tips, Serialization is awesome i use it all the time, the thing is, you are actually saving on a Thread that actually encountered a problem, are you expecting a magical call to onStop() ? so either
You call your save methods routinely on a different thread, so it keeps on saving irrespective of what happens.-after all its a game-
You maybe add a try/catch to your code and catch certain exceptions and manually call a save method on a different Thread, well with this you need sick Encapsulation. This might not serve you well as errors like noSuchMethod etc, can not be caught so a force close might happen
either way your preference.

Android4OpenCV: setting resolution at startup

I'm using Android4OpenCV to do some live image processing, and I'd like to use the smallest resolution the camera can offer. The default resolution is the largest the camera can offer.
I'm looking at the 3rd example, which allows the user to change resolutions via a menu. I'd like to modify that example to change the resolution at startup instead of requiring the user go through the menu. To do that, I simply add two lines to the otherwise empty onCameraViewStarted() function:
public void onCameraViewStarted(int width, int height) {
android.hardware.Camera.Size res = mOpenCvCameraView.getResolutionList().get(mOpenCvCameraView.getResolutionList().size()-1);
mOpenCvCameraView.setResolution(res);
}
And the thing is, this works perfectly fine on my Galaxy Nexus, running Android 4.2.2. The app starts up, and the resolution is set correctly.
However, when I run the exact same app on a Nexus 7 tablet, running Android 5.1, the app hangs on the call to setResolution(). Actually it works okay one time, but then hangs the second time you try to run it- even if you completely exit the app, remove it from the running apps, or restart the device. Other users are reporting the same error as well, so it's not just the Nexus 7 device- in fact, my Galaxy Nexus seems to be the only device where this works.
Specifically, the application goes into the setResolution() function, which then calls org.opencv.android.JavaCameraView.disconnectCamera(), which looks like this:
(Note: this code is internal to the OpenCV4Android library, this is not my code)
protected void disconnectCamera() {
/* 1. We need to stop thread which updating the frames
* 2. Stop camera and release it
*/
Log.d(TAG, "Disconnecting from camera");
try {
mStopThread = true;
Log.d(TAG, "Notify thread");
synchronized (this) {
this.notify();
}
Log.d(TAG, "Wating for thread");
if (mThread != null)
mThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
mThread = null;
}
/* Now release camera */
releaseCamera();
}
Looking at the logs, I can see that the thread gets stuck on the synchronized(this) line. The only other thing that synchronizes on that Object is the inner JavaCameraView.CameraWorker class, which is the mThread variable in the above code, started by the JavaCameraView class:
(Note: this code is internal to the OpenCV4Android library, this is not my code)
private class CameraWorker implements Runnable {
public void run() {
do {
synchronized (JavaCameraView.this) {
try {
JavaCameraView.this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (!mStopThread) {
if (!mFrameChain[mChainIdx].empty())
deliverAndDrawFrame(mCameraFrame[mChainIdx]);
mChainIdx = 1 - mChainIdx;
}
} while (!mStopThread);
Log.d(TAG, "Finish processing thread");
}
}
I've tried futzing with that code, changing the notify() to notifyAll(), and maintaining a List of CameraWorker threads and joining each one. But no matter what, the app still hangs at the disconnectCamera() call.
My questions are:
How can I modify the third OpenCV4Android example so that its resolution is set at startup?
What is causing the app to hang?
Why does this work on some devices but not others?
Edit: I haven't received any comments or answers, so I've crossposted to the OpenCV forums here.
Edit 2: As per cyriel's suggestion, I've tried setting the resolution after several frames have gone by:
int frames = 0;
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
frames++;
if(frames == 6){
android.hardware.Camera.Size res = mOpenCvCameraView.getResolutionList().get(mOpenCvCameraView.getResolutionList().size()-1);
mOpenCvCameraView.setResolution(res);
}
return inputFrame.rgba();
}
However, now this gets stuck in the same exact place, even on my Galaxy Nexus, which works if I set the resolution in the onCameraViewStarted() function. I've tried increasing the frame count to 7 and even 100, but I always get stuck in the same place.
The most important question in your situation is whether it's working if you don't modify the code at all - are you able to change the resolution (via menu) without crashing the app?
If yes than the answer most likely is simple - it's the same bug in OpenCV as in Windows version: before changing camera resolution or fps (and most likely any property) you need to grab at least one (use 3-5 to be sure) frame before changing this property.
If no than most likely there is nothing you can do on your own - fill the bug report and wait for comments. The only alternative is to use other library to grab frames from camera and than convert it to OpenCV object.

How to close external programs (Powerpoint) running on the native desktop using Java?

I have to create an application that will automatically open a powerpoint file, let it play through, and then close it. Not only do I need to figure out HOW to close it, but I also must detect when it closes or stops.
First option:
I know how long each powerpoint will play for, so I can hardcode when to close the file. I just need to know how to do that. There are no methods in the desktop class (that I could find) for closing.
Second option:
If someone knows a microsoft powerpoint api that lets me open powerpoints and use java to progress through the slideshow and get the state or something, that'd be great. I wouldn't have to go into each presentation and count the number of slides and the transition timer on each slide.
The opening, letting it play, and closing it is a small part of the app I need to create. But here is what I have so far with regards to THIS problem:
File myfile = new File("PowerPoint.ppsx");
try {
Desktop.getDesktop().open(myfile);
} catch (IOException ex) {
Logger.getLogger(Sc.class.getName()).log(Level.SEVERE, null, ex);
}
Probably this is the solution how to close external program:
http://www.java-forums.org/new-java/59691-close-another-program.html#post285956
If you want to detect when program has stopped running then you can start new thread with loop which from time to time will check if the program process is still running, using the same method as mentioned in link.
This is solution only for one (Windows) platform, Java is not the best choice for such tasks.
Here a solution using JNA. First we get the handle, we search using the "class name" of the window. You can determine the class name for a specific program (in this case Powerpoint) with a special utility like Spy++ (included with Visual Studio). It's possible to make the search more precise using the class name and the window caption (but here I use only the class name) so if you have more than one presentation running ... you may not close the good one!.
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.platform.win32.WinDef.HWND;
// https://github.com/twall/jna#readme
// you need 2 jars : jna-3.5.1.jar and platform-3.5.1.jar
public class KillMyPP {
public static void main(String[] args) {
HWND hwnd = User32.INSTANCE.FindWindow("screenClass", null);
if (hwnd == null) {
System.out.println("PPSX is not running");
}
else {
User32.INSTANCE.PostMessage(hwnd, WinUser.WM_QUIT, null, null);
}
}
}

Better Way to Test Presence of a Value in a Bundle?

I have an activity to play a game. The user may be resuming from a saved state or initiating a new game. If resuming, the identifier for the game to resume is passed to the activity in the bundle. If it is a new game, that part of the bundle isn't passed, and is therefore null. I currently implement this as follows...
Bundle bundle = this.getIntent().getExtras();
int GameNumberToResume;
boolean StartNewGame = false;
try
{
GameNumberToResume = bundle.getInt("GameToResume");
}
catch (Exception e)
{
System.out.println("Exception Catch, so we start a new game.");
StartNewGame = true;
System.out.println((e.toString()));
}
...and it works. StartNewGame drives the decision tree on if we are starting a new one or resuming a saved one, and if we are resuming, GameNumberToResume has the game ID to resume. However, Android Studio throws the soft warning...
Variable 'GameNumberToResume' is assigned but never accessed.
...because in the parts of the decision tree when I need the value of the game to resume, I pull it straight from the bundle via bundle.getInt("GameToResume").
So here's my question: What should I do different? I can make the warning go away by referencing the variable GameNumberToResume downstream instead of pulling it from the bundle, but it doesn't seem to me like that would change anything. The intent of the warning is to point out that I'm wasting memory, and if I do this, I still have two things in scope that both contain the same value.
Is there a way to detect the absence or presence of "GameToResume" in
the bundle without doing a variable assignment in a try/catch loop?
If I move the declaration inside the try part of the loop, then
fire off a System.gc(); after the catch portion of the loop,
would it free up what was used by the variable GameNumberToResume ?
I know in this specific case it probably doesn't matter, but it is simple enough to follow and illustrates a general hole in my understanding of how to efficiently code Android.
Checkout
bundle.containsKey ("GameToResume");
it will return whether this key is there or not in bundle.
Do not use the try-catch here. And you can initialise the game number like int GameNumberToResume=Integer.MAX_VALUE. Then remove the try-catch. Just use if(xx==Integer.MAX_VALUE).
In my opinion, try-catch can only use for the unknown error or unpredictable situation. Here, you know everything.
You can utilize getInt second parameter to put default value, like this.
Bundle bundle = this.getIntent().getExtras();
// Don't forget NullPointerException
if(bundle != null){
final int IMPOSSIBLE_VALUE = -1; // default value
boolean startNewGame = false;
int gameNumberToResume = bundle.getInt("GameToResume", IMPOSSIBLE_VALUE);
if(gameNumberToResume != IMPOSSIBLE_VALUE){
startNewGame = true;
// continue ..
}
}

Categories