wallpaperPreview() - works on setup() only?

Hi!
I was tinkering with a live wallpaper I made on Christmas 2018 . Last year I inserted a button which appeared in preview mode. This year I wanted to put some functionality on it, but I am hitting a rock every time.

The last strange thing I have found is that you can’t trust wallpaperPreview() when you are outside the setup() function. On draw(), it gets random values, displaying preview elements when not in preview or saying preview is off some seconds after starting the preview. I guess wallpaperPreview() value comes from the isPreview() android function, wich is available on start of the wallpaper only.

But that is not documented on the wallpaperPreview() help page.

Also, I am unable of getting mouse clicks inside the wallpaper, preview or not preview. Should I enable some specific wallpaper permission to be able to read mouse position inside preview?

N.B. Excuse me for not posting my code here. It is on my android phone and it is charging now, with a charging-only wire.

I have tested the wallPaperPreview function with two different codes now on KitKat 4.4 and Lollipop 5.1 but did not get any error. Also getting mouse touch on screen works well with if(mousePressed) in draw() as well as in void mousePressed(). I can not test the external mouse clicks you mentioned.(do not have one). I will wait for your code.
There is no need for any permission.

1 Like

Ok, here is my code:


/* Invasión de copos de nieve */
/* José G. Moya Yangüela - Demasiado tarde para la edición de navidad--- */
/* Pero lo vamos a intentar... */


import android.app.WallpaperManager.*;
int modo=1;
int fps=10;
float btnleft,btntop,btnright,btnbottom;
float centerx;
 float centery;
 float angle[];
Copo copos[];  
boolean isPre=false;
 void setup (){
    isPre=wallpaperPreview();
    centerx=width/2;
    centery =height/2;
    copos=new Copo[0];
    colorMode(HSB);
    frameRate(fps);
    btnleft=0;
    btntop=0;
    btnright=0;
    btnbottom=0;
 }

 void draw (){
  background(0);
    switch (modo) {
      case 2: drawmenu(); break;
      case 1:
      default: drawcopo();
      
    }
 }
 
 void drawcopo(){
   int f;
   if (copos.length<255){
    copos=(Copo[]) append(copos,new Copo(random(width),random(height),random(50)));
   }
   for (f=0;f<copos.length;f++){
     /**/ copos[f].moverx(int((copos[f].lenmax/4)*cos(frameCount*PI/90)));
      copos[f].movery(int(abs(
          (copos[f].lenmax/4)
          *sin(frameCount*PI/90)
         )
      ));
     /* */
      copos[f].dibujar();
      copos[f].colorB--;
      if (copos[f].colorB<=0) {
        
       copos[f]=copos[copos.length-1];
       copos[copos.length-1]=new Copo(random(width),random(height),random(50));
      }
   }
   /* DEBUG START */
   text (
        str(wallpaperPreview())+" "+ str(isPre),
        width/2,
        height/2
    );
    /* DEBUG END */
  
    if (isPre){
      menu();
    }
 }

void drawmenu(){
  fill(255);
  textAlign(RIGHT);
  textSize(24*displayDensity);
  text("Volver",width,height-200);
  btnleft=textWidth("Volver");
  btntop=height-(textAscent()+150);
  btnright=width;
  btnbottom=height+textDescent()-150;
  textAlign(CENTER, CENTER);
  text("FPS: "+fps, height/3, width/2);
}
class Copo{
   int colorH;
   int colorS;
   int colorB;
   float cx;
   float cy;
   float lenmax;
   void moverx(int dx){
     this.cx+=dx;
   }
   void movery(int dy){
     this.cy+=dy;
   }
  int len[]={4,4,4,4};

    Copo(float icx,float icy,float ilenmax){
      this.colorH=int(random(255));
      this.colorS=int(random(255));
      this.colorB=200;
     this.cx=icx;
     this.cy=icy;
     this.lenmax=ilenmax;


    int lenacum=0;
    lenacum =0;
    int l;
    for (l=0;l <4;l++){
        this.len [l]=int(random(0,this.lenmax-lenacum));
        lenacum+=len [l];
      }
    }
   
    void dibujar(){
      
      stroke(color(this.colorH,this.colorS,this.colorB));
      float angle;
      for(angle=0;angle<2*PI;angle+=PI/3){
        
        
      line (this.cx,this.cy,this.cx+this.lenmax*cos (angle),this.cy+this.lenmax*sin (angle));
      this.brazo (this.cx,this.cy,angle,1);
    
    }
  }
  void brazo (float bx,float by,float angle,int nivel){
    line (bx, by, bx+len[nivel]*cos(angle-PI/6), by+len[nivel]*sin(angle-PI/6));
       if (nivel <3){
    this.brazo(bx+len[nivel]*cos(angle-PI/6), by+len[nivel]*sin(angle-PI/6), (angle-PI/6),nivel+1 );
    }
    line (bx, by, bx+len[nivel]*cos(angle+PI/6), by+len [nivel]*sin(angle+PI/6));
    if (nivel <3){
       this.brazo(bx + len[nivel]*cos(angle+PI/6), by+len[nivel]*sin(angle+PI/6), (angle+PI/6), nivel+1 );
    }
  }
   
 }

void menu(){
  fill(255);
  textAlign(RIGHT);
  textSize(24*displayDensity);
  text("Administrar",width,height-150);
  btnleft=width-textWidth("Administrar");
  btntop=height-(textAscent()+150);
  btnright=width;
  btnbottom=height+textDescent()-150;
  rectMode(CORNERS);
  noFill(); stroke(255);
  rect(btnleft, btntop,btnright,btnbottom);
};

void mouseClick(){
  
  if (isPre==false) return;
  
  if (mouseX>=btnleft & mouseX <= (btnright)){
    if (mouseY>= btntop & mouseY<= (btntop)) {
      modo=(modo==2) ? 1 :2;
    }
   }
}
 
 

I’ve added the code between /DEBUG START/ and /DEBUG END/. Today it is working as expected (false false or true true, saying wallpaperPreview() value does not change until the app is selected as live wallpaper), but yesterday it gave me values such as “true false” or “false true”, and the menu button was displayed in the live wallpaper until I changed wallpaperPreview with isPre (=wallpaper preview value on start).

Very nice design. I left it as wp on my device.
However I had to take down the cops.lenth to 50, because on both my devices it slows down to lower as 2 fps. You will see that if you use frameRate ( not fps) directly in the default case. (When you toggle menu/draw in your code the frameRate will immediately rise to highest because you are not drawing) Further I used mousePressed to toggle without problems. My suggestion is drawing a group of stars in setup(), store them, and only move them in draw, because there is some heavy real time calculation in draw() slowing down the sketch and stealing processing power.

Here is the definitive version. I tried to use saveJSONObject and loadJSONObject instead of binary files, but I have found no documentation about hiw to check for existence of JSON files.


/* Invasión de copos de nieve */
/* José G. Moya Yangüela - Demasiado tarde para la edición de navidad--- */
/* Pero lo vamos a intentar... */


import android.app.WallpaperManager.*;
int modo=1;
int fps=10;
int coposMax=255;
float btnleft,btntop,btnright,btnbottom;
float centerx;
float centery;
float angle[];
Copo copos[];
Boton botones[];
byte configuration[]={byte(coposMax),byte(fps)};
byte conf2[];
boolean isPre=false;
String filename="configuration.dat";


void setup (){
    if ((conf2=loadBytes(filename))
        ==null){
      /* do nothing */
    } else {
       configuration=conf2;
      coposMax=int(configuration[0]);
      fps=int(configuration[1]);
    }
    isPre=wallpaperPreview();
    centerx=width/2;
    centery =height/2;
    copos=new Copo[0];
    colorMode(HSB);
    frameRate(fps);
    btnleft=0;
    btntop=0;
    btnright=0;
    btnbottom=0;
 }

 void draw (){
  background(0);
    switch (modo) {
      case 2: drawmenu();
      case 1:
      default: drawcopo();
      
    }
 }
 
 void drawcopo(){
   int f;
   if (copos.length<coposMax){
    copos=(Copo[]) append(copos,new Copo(random(width),random(height),random(50)));
   }
   for (f=0;f<copos.length;f++){
     /**/ copos[f].moverx(int((copos[f].lenmax/4)*cos(frameCount*PI/90)));
      copos[f].movery(int(abs(
          (copos[f].lenmax/4)
          *sin(frameCount*PI/90)
         )
      ));
     /* */
      copos[f].dibujar();
      copos[f].colorB--;
      if (copos[f].colorB<=0) {
        
       copos[f]=copos[copos.length-1];
       copos[copos.length-1]=new Copo(random(width),random(height),random(50));
      }
   }
   /* DEBUG START */
   /* text (
        str(wallpaperPreview())+" "+ str(isPre),
        width/2,
        height/2
    );
    */
    /* DEBUG END */
  
    if (modo==1 && isPre){
      menu();
    }
 }



class Copo{
   int colorH;
   int colorS;
   int colorB;
   float cx;
   float cy;
   float lenmax;
   void moverx(int dx){
     this.cx+=dx;
   }
   void movery(int dy){
     this.cy+=dy;
   }
  int len[]={4,4,4,4};

    Copo(float icx,float icy,float ilenmax){
      this.colorH=int(random(255));
      this.colorS=int(random(255));
      this.colorB=200;
     this.cx=icx;
     this.cy=icy;
     this.lenmax=ilenmax;


    int lenacum=0;
    lenacum =0;
    int l;
    for (l=0;l <4;l++){
        this.len [l]=int(random(0,this.lenmax-lenacum));
        lenacum+=len [l];
      }
    }
   
    void dibujar(){
      
      stroke(color(this.colorH,this.colorS,this.colorB));
      float angle;
      for(angle=0;angle<2*PI;angle+=PI/3){
        
        
      line (this.cx,this.cy,this.cx+this.lenmax*cos (angle),this.cy+this.lenmax*sin (angle));
      this.brazo (this.cx,this.cy,angle,1);
    
    }
  }
  void brazo (float bx,float by,float angle,int nivel){
    line (bx, by, bx+len[nivel]*cos(angle-PI/6), by+len[nivel]*sin(angle-PI/6));
       if (nivel <3){
    this.brazo(bx+len[nivel]*cos(angle-PI/6), by+len[nivel]*sin(angle-PI/6), (angle-PI/6),nivel+1 );
    }
    line (bx, by, bx+len[nivel]*cos(angle+PI/6), by+len [nivel]*sin(angle+PI/6));
    if (nivel <3){
       this.brazo(bx + len[nivel]*cos(angle+PI/6), by+len[nivel]*sin(angle+PI/6), (angle+PI/6), nivel+1 );
    }
  }
   
 }
class Boton {
  public float cx;
  public float cy; 
  public float radius;
  public String texto;
  public int code;
  Boton(String btext, float bx, float by, float bradius, int bcode){
    pushStyle();
    noFill();
    stroke(255);
    this.cx=bx;
    this.cy=by;
    this.radius=bradius;
    this.texto=btext;
    this.code=bcode;
    ellipseMode(RADIUS);
    ellipse(this.cx, this.cy, this.radius, this.radius);
    fill(255);
    textAlign(CENTER, CENTER);
    text(this.texto,cx,cy);
    popStyle();
  }
  public boolean check( float xt,float yt){
    if ( dist(xt, yt, this.cx, this.cy)< this.radius){
      return true;
    }
    return false;
  }
}

void menu(){
  fill(255);
  textAlign(RIGHT);
  textSize(24*displayDensity);
  text("Administrar",width,height-150);
  btnleft=width-textWidth("Administrar");
  btntop=height-(textAscent()+150);
  btnright=width;
  btnbottom=height+textDescent()-150;
  rectMode(CORNERS);
  noFill(); stroke(255);
  rect(btnleft, btntop,btnright,btnbottom);
};
void drawmenu(){
  pushStyle();
  fill(255);
  textAlign(RIGHT);
  textSize(24*displayDensity);
  text("Volver",width,height-150);
  btnleft=width-textWidth("Volver");
  btntop=height-(textAscent()+150);
  btnright=width;
  btnbottom=height+textDescent()-150;
  
  rectMode(CORNERS);
  noFill(); stroke(255);
  rect(btnleft, btntop,btnright,btnbottom);
  textAlign(CENTER,CENTER);
  
  
  text("Max FPS: "+str(fps), width/2, height/4);
   text("Real FPS: "+str(round(frameRate*10)/10), width/2, height/4+textAscent()+textDescent());
  text("Copos (Flakes): "+str(coposMax), width/2, height/2);
  
  noFill();
  botones=new Boton[] {
    new Boton("-",2*textAscent(), height/4, textAscent(), 1),
    new Boton("+",width-2*textAscent(), height/4, textAscent(), 2),
    new Boton("-",2*textAscent(), height/2, textAscent(), 3),
    new Boton("+",width-2*textAscent(), height/2, textAscent(), 4),
  };
  
  ellipseMode(RADIUS);
  ellipse(2*textAscent(),height/4,textAscent(),textAscent());
  text("-",2*textAscent(),height/4);
  popStyle();
}
void mousePressed(){
  
  if (isPre==false) return;
  if (modo==2) {
    int code=-1;
    for (int f=0; f<botones.length; f++){
      if (botones[f].check(mouseX,mouseY)){
        code=botones[f].code;
        break;
      }
    }
    if (code>=0){
      switch(code){
        case 1:
           fps=max(5, fps-5);
           frameRate(fps);
           break;
        case 2:
           fps=min(30,fps+5);
           frameRate(fps);
           break;
        case 3:
           coposMax=max(15,coposMax-16);
           copos=(Copo[]) subset(copos,0,min(copos.length,coposMax));
           break;
        case 4:
           coposMax=min(255,coposMax+16);
           break;
      }
      configuration[0]=byte (coposMax);
      configuration[1]=byte (fps);
      saveBytes(filename,configuration);
    }
  }
  
  if (mouseX>=btnleft && mouseX <= (btnright)){
    if (mouseY>= btntop && mouseY<= (btnbottom)) {
      modo=(modo==2) ? 1 :2;
    }
   }
}

When run in preview, you can choose number of flakes and max fps, and this setting will be saved for your screensaver.

(This code is based on a script I originally uploaded to MedialabPrado #programalaplaza )

1 Like

Working very well ( using limit 47).:+1:

A couple improvements

First: on Copo() constructor, assign random value to bright, so flakes do not disappear at same time.

/* was: */
//this.colorB=200;
/* new code:*/
this.colorB=100+int(random(100));

Second: in Samsung wallpaper selector, the menues were bad-looking.
This is the new drawmenu() function:

void drawmenu(){
  pushStyle();
  fill(255);
  textAlign(RIGHT);
  textSize(24*displayDensity);
  text("Volver",width,height-150);
  btnleft=width-textWidth("Volver");
  btntop=height-(textAscent()+150);
  btnright=width;
  btnbottom=height+textDescent()-150;
  
  rectMode(CORNERS);
  noFill(); stroke(255);
  rect(btnleft, btntop,btnright,btnbottom);
  textAlign(CENTER,CENTER);
  
  
  text("Max FPS: ", width/2, height/4);
  text(str(fps), width/2, height/4+2*textAscent());
  text("Real FPS: "+str(round(frameRate*10)/10), width/2, height/4+4*textAscent());
  text("Copos (Flakes): ", width/2, height/2);
  text(str(coposMax), width/2, height/2+2*textAscent());
  
  noFill();
  botones=new Boton[] {
    new Boton("-",width/2-(textWidth("00")+2*textAscent()), 
              height/4+2*textAscent(),
              textAscent(), 1),
    new Boton("+",width/2+textWidth("00")+2*textAscent(), 
              height/4+2*textAscent(),
              textAscent(), 2),
    new Boton("-",width/2-(textWidth("00")+2*textAscent()), 
              height/2+2*textAscent(),
              textAscent(), 3),
    new Boton("+",width/2+textWidth("00")+2*textAscent(), 
              height/2+2*textAscent(),
              textAscent(), 4)
  };
1 Like