📜 ⬆️ ⬇️

Screensaver on J2ME or Back to the past. Part one

Good day!

Introduction


In the courtyard of the third of January, and the soul now and then requires you to write some program. Without thinking twice, I remembered that I had once proposed a correction to the author of the Splash Screen topic on J2ME , after which my doubts about what to write finally disappeared. Today, I invite you to plunge into the world of "ordinary dialers" and write an application for them - this will be an ordinary screensaver.


So let's get started


First you need to set yourself the necessary software development. I think, it is not necessary to paint that it is necessary to set yourself on a PC to compile and run our application, since On the Internet, such instructions can be found in five seconds. Here , for example. Personally, I compile all the source code for J2ME applications on the "regular caller". Yes, yes, there are craftsmen on the Russian land who have ported the compiler with the pre-qualifier to the J2ME platform.
After everything is established, it would be nice to recall the theory itself, starting with the application's J2ME device and ending with the directives of the manifesto of our application. However, if you do not know what's what, then do not worry - a bit of theory on developing applications for J2ME will be discussed in this topic.
')

Anatomy of a J2ME application


In general, an application in J2ME is called a MIDlet. Why so, you will find out further.

javax.microedition.midlet.MIDlet

A J2ME application is nothing more than a class inherited from the MIDlet class from the javax.microedition.midlet package. This class is the “heart” of the MIDlet. In our class, we must declare the three methods necessary for the functioning of our application:
public void startApp() { //        } public void pauseApp() { //   ,      , SMS  .. } public void destroyApp(boolean unconditional) { //    ,   . //  ... } 

The fact is that this method is indicated as necessary for implementation, while it does not carry practical use. The startApp () and pauseApp () methods are used by AMS itself, and destroyApp () is not. By tradition, usually the block of this function is as follows:
 public void destroyApp(boolean unconditional) { notifyDestroyed(); //      } 

As you can see, the notifyDestroyed () function, not destroyApp (), controls the termination of the application life cycle. Well, okay, the purpose of the latter will remain a mystery. We will not be distracted, and move on.

javax.microedition.lcdui.Display

The next step in implementing our application is to get a link to the Display object of the javax.microedition.lcdui package. As you might have guessed, this is done to get the opportunity to work with the screen, the forms ( javax.microedition.lcdui.Form ) or the canvas ( javax.microedition.lcdui.Canvas ) and switch between them. We can get the link as follows:
 Display dsp = Display.getDisplay(this); //  ... 

The deed is done, go to the next step.

javax.microedition.lcdui.game.GameCanvas

Immediately I want to note that with the advent of the GameCanvas class, it began to force out the usual Canvas because of the impossibility of double buffering out of the box, as such. Therefore, as a canvas, I suggest using GameCanvas . No sooner said than done.
GameCanvas and Canvas differ only in two ways: the first has already been specified (this is double buffering), and the second is the need to declare the paint method in the last. For clarity, I will provide the following canvas implementation code using Canvas :
 import javax.microedition.lcdui.Canvas; import javax.microedition.lcdui.Graphics; public class OurCanvas extends Canvas { //   Canvas public void paint(Graphics g) { int w = getWidth(); //    int h = getHeight(); //      g.setColor(0xffffff); //    g.fillRect(0,0,w,h); //      } } 

In the paint () method, we do all the drawing of graphic primitives. This approach is not particularly effective for many reasons, one of which is the desire to share logic.
GameCanvas allows you to make logic to other methods, classes, etc. Like this:
 import javax.microedition.lcdui.Canvas; import javax.microedition.lcdui.Graphics; public class OurCanvas extends GameCanvas implements Runnable { //   GameCanvas    Runnable,    Thread public void run() { Graphics g = getGraphics(); //     Graphics //           int w = getWidth(); //    int h = getHeight(); //      g.setColor(0xffffff); //    g.fillRect(0,0,w,h); //      } } 

Here I made a mistake: I did not take the declaration of the Graphics object somewhere inside the declaration of the class itself to the place of the declaration of variables, i.e. The code should look like this:
 import javax.microedition.lcdui.Canvas; import javax.microedition.lcdui.Graphics; public class OurCanvas extends GameCanvas implements Runnable { Graphics g = getGraphics(); int w = getWidth(); int h = getHeight(); public void run() { g.setColor(0xffffff); g.fillRect(0,0,w,h); isSomethingDone(); } public void isSomethingDone() { g.setColor(0xababab); g.drawLine(25,25,125,125); } } 

Something like this. That's all - the necessary knowledge base for the implementation of our plans we have. Go!

We proceed to the development


Our application will consist of several classes:
Meet midlet.java:
 import javax.microedition.midlet.MIDlet; import javax.microedition.lcdui.*; import java.util.Timer; public class midlet extends MIDlet { Timer timer; midletTimerTask task; midletCanvas canvas; public midlet () { canvas = new midletCanvas(this); //   timer = new Timer (); task = new midletTimerTask (canvas); //  ,    timer.scheduleAtFixedRate(task,10,10); //  10  // 10  -  .    repaint  , //     ,    in } protected void startApp() { //     Display.getDisplay(this).setCurrent (canvas); } protected void pauseApp() {} protected void destroyApp(boolean unconditional) {} public void exitMIDlet() { notifyDestroyed(); } } 

Next, the canvas itself is midletCanvas.java:
 import javax.microedition.lcdui.*; class midletCanvas extends Canvas { midlet midlet; random Random; static int [] PlasmaTab = { //   - 256  32,32,33,34,35,35,36,37,38,39,39,40,41,42,42,43, 44,45,45,46,47,47,48,49,49,50,51,51,52,52,53,54, 54,55,55,56,56,57,57,58,58,59,59,59,60,60,60,61, 61,61,62,62,62,62,63,63,63,63,63,63,63,63,63,63, 63,63,63,63,63,63,63,63,63,63,62,62,62,62,62,61, 61,61,60,60,60,59,59,58,58,58,57,57,56,56,55,54, 54,53,53,52,52,51,50,50,49,48,48,47,46,46,45,44, 43,43,42,41,40,40,39,38,37,37,36,35,34,33,33,32, 31,30,30,29,28,27,26,26,25,24,23,23,22,21,20,20, 19,18,17,17,16,15,15,14,13,13,12,11,11,10,10, 9, 9, 8, 7, 7, 6, 6, 5, 5, 5, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,10,11,11,12,12,13,14,14,15,16,16,17,18,18,19, 20,21,21,22,23,24,24,25,26,27,28,28,29,30,31,31 }; //,      ,   //  32* (1+ sin (x*(2*pi/255)),      static int Delta = 6; //     static int Yold_pos=0, Yold_asp=0, Xold_pos=0, Xold_asp=0; int Ynew_pos, Ynew_asp, Xnew_pos, Xnew_asp, x, y, Color; static int Width, Height; //    static boolean in = false; //  Graphics gbuffer; //   Image screen; //  public midletCanvas (midlet midlet) { this.midlet = midlet; Random = new random (); setFullScreenMode (true); //   MIDP 2.0 Width = getWidth (); Height = getHeight (); screen=Image.createImage(Width,Height); gbuffer=screen.getGraphics(); //   gbuffer, draw (gbuffer); //      ! } void draw (Graphics g) { //      in = true; Ynew_pos = Yold_pos; Ynew_asp = Yold_asp; for (y=0; y<Height; y+=Delta) { Xnew_pos = Xold_pos; Xnew_asp = Xold_asp; for (x=0; x<Width; x+=Delta) { Color = PlasmaTab[Ynew_pos]+ PlasmaTab[Ynew_asp]+ PlasmaTab[Xnew_pos]+ PlasmaTab[Xnew_asp]; g.setColor(((255-Color)<<16 | Color<<8 | 128+(Color>>1))); g.fillRect (x,y,Delta,Delta); Xnew_pos += 1; if (Xnew_pos > 255) Xnew_pos=0; Xnew_asp += 7; if (Xnew_asp > 255) Xnew_asp=0; } Ynew_pos += 2; if (Ynew_pos > 255) Ynew_pos=0; Ynew_asp += 1; if (Ynew_asp > 255) Ynew_asp=0; } Xold_pos -= 2; if (Xold_pos<0) Xold_pos=255; Xold_asp += Random.get(8); if (Xold_asp > 255) Xold_asp=0; Yold_pos += 4; if (Yold_pos > 255) Yold_pos=0; Yold_asp -= Random.get(6); if (Yold_asp<0) Yold_asp=255; in = false; } protected void paint (Graphics g) { if (in == true) return; //      g.drawImage(screen,0,0,0); draw (gbuffer); } public void keyPressed(int keyCode) { switch (keyCode) { //   # case Canvas.KEY_POUND: midlet.exitMIDlet(); break; } } } 

Next in a row is the timer - midletTimerTask.java:
 import java.util.TimerTask; import javax.microedition.midlet.MIDlet; class midletTimerTask extends TimerTask { midletCanvas canvas; public midletTimerTask (midletCanvas canvas) { this.canvas = canvas; } public final void run() { canvas.repaint(); } } 

And finally, the implementation of the selection of random numbers - random.java
 import java.util.Date; import java.util.Random; class random { //-    private Random r; private Date d; public random () { d = new Date (); r = new Random (d.getTime()); } public int get (int max) { //    [0,max-1] int n=r.nextInt()%max; return (n<0 ? -n : n); } } 


Scandals, intrigues, investigations


My source does not want to compile. Rather, they are compiled, but not what I want is executed. Late night, so your humble servant did not have to take his source code. I apologize for formatting the code - I'll fix it tomorrow.

Next thing is the technique


Compilation and conversion. I leave this step on you.

MANIFEST.MF


I suggest you tinker with this file, and it is located in the META-INF directory . After all, if we make a screensaver, then he must conduct himself accordingly. Unfortunately, this behavior is available only to phones from Sony Ericsson. Let's add the following line to it:
  SEMC-StandbyApplication: Y 


What we did


We made it possible to download our screensaver as wallpaper. To do this, you need to throw the MIDlet into the phone. Next, go to the "Applications", we find ours. The next step is to press the right soft key and select the item “Like background. picture". Choose - eat filed. You will see the following

That's what happened






All you need


Sources you can take on Pastebin. here they are:
midlet.java
midletCanvas.java
midletTimerTask.java
random.java

Conclusion


That's all. In just a few steps, we wrote a MIDlet. Nowadays, J2ME is gradually going nowhere and maybe you don’t have a pipe like this, but while Oracle is engaged in supporting it, who knows, there will be more. I hope you were interested.

See you soon!

Source: https://habr.com/ru/post/135672/


All Articles