Adding the ability to SatStat to copy the current location to the clipboard

If you like open source applications, and use GPS on your phone, you probably have heard of SatStat. It is a really great open source option for monitoring your location with GPS, as well as several other nifty perks. The only downside I could see to this application, is that it did not have a way to copy your current location to the clipboard so that you could share it with someone else.

Often, when using this app, I end up taking a screenshot of my location and sending that to someone else, but this is very tedious for them in the form of wasted data transmitted that they now have to manually sort through and retype the coordinates of the picture into a text format for use in a GPS app or Google maps.

So, I decided to quit whining and do something about it.

It was fairly simple, actually. You can see my commit here. All I did was fork the SatStat GitHub, download the fork, and added a menu option to copy the current location ( the one being displayed to the user) to the clipboard. I followed that up with a pull request, which also updates the referenced issue tracker, where other users were requesting this function as well.

I could have actually used the “location” that was being reported to the system, rather than the displayed location, but I did it by displayed location for three reasons:

  1. If there is no location information from the system. The displayed location still has  ” – – ” displayed in it. So, the copy to clipboard command will not error, because it will simply copy ” – – ” as your location.
  2. The user has the choice of how the location is displayed. Rather than weed through all the settings and then copy the system reported information, and then edit it to match the user preferences for display, it simply copies the text as displayed, which already is per the user’s preference. I figure if they wanted it to be in MGRS, or decimal minutes, they would already have set their displayed information to that.
  3. To keep “what you see is what you get”. The location displayed to them is exactly the information they will copy to the clipboard. This helps in the event that the information displayed is not updated, they can copy the last known location, as the information displayed is only updated when the location has changed.

I tried to keep the code as clean and simple as possible. Hopefully they will add that to the regular app. If not, well, I suppose that I will just start using my edited personal copy, so I can save my own position to the clipboard.

Linux – keep it simple.

What is the difference between isTouched and justTouched?

Fortunately, it did not take long to figure this out, but as a beginning java programmer using libGDX, I couldn’t quite figure out the difference between isTouched and justTouched right off the bat. A Google search actually told me the answer, but at the time I did not understand what that answer meant, or when you might use them.

So, to dumb it down for simple folks like me:

  • justTouched – When used in a render method, it will only count the first time you touch the screen, like a “touch down”, but does not render “holding down” the screen. It also does not care about “touch up” or releasing the screen. You might use this to tap an object that you want to register the tap, but do not want it to continue registering that you are holding it. This could be useful to pop a balloon in a game, tap a button, click on something, etc.
  • isTouched – When used in a render method, it will continuously count that you are touching the screen until you let go. This allows you to “hold down” on the screen. Some examples that I could think of for use might be drawing with a paintbrush, turning a page, a button that must be held down, pushing a rock uphill, etc.

Both of these tools have their places, and I could see reasons to implement one or the other depending on your needs. Hopefully that helps someone else out there.

Linux – keep it simple.

How to “touch” objects in libGDX

There are actually many ways that one can “touch” an object in libGDX. You can create scenes with stages and characters and actors, for one. You could do sprite comparisons as another. I decided to go a simple route with intersections.

The goal is to be able to detect that the user has tapped on or touched an object that is displayed on the screen. This is really handy, as it will allow you to manipulate objects to move them, pop balloons, draw pictures, press switches, and more. Pretty much all the usual things that you do in a game. And this is just my rendition of how to do that.

Obviously, the nature of the game would determine if this was a useful method or not. Depending on what you are trying to accomplish, this may or may not be useful. You can check out the whole open source for the project on my GitHub.

So, I first needed some objects to touch, and an object for where I touched under the class:

Circle centerCircle, leftCircle, rightCircle, myTouch;

Then I declared those circles under the onCreate method:

centerCircle = new Circle();
leftCircle = new Circle();
rightCircle = new Circle();
myTouch = new Circle();

Finally, I used shaperenderer to draw them under the render method:

shapeRenderer.begin(ShapeRenderer.ShapeType.Filled); // For visualizing collision shapes.

if (colorChanger == 0) {
shapeRenderer.setColor(Color.BLUE); // For visualizing collision shapes.
} else if (colorChanger == 1) {
shapeRenderer.setColor(Color.RED); // For visualizing collision shapes.
} else {
shapeRenderer.setColor(Color.GREEN); // For visualizing collision shapes.
} // Cool color changing affect, so you know you touched a circle.

 

leftCircle.set(Gdx.graphics.getWidth()*2/3,
Gdx.graphics.getHeight()*2/3,
100); // Set the circle.

centerCircle.set(Gdx.graphics.getWidth()/2,
Gdx.graphics.getHeight()/2,
100); // Set the circle.

rightCircle.set(Gdx.graphics.getWidth()*1/3,
Gdx.graphics.getHeight()*1/3,
100); // Set the circle.

shapeRenderer.circle(centerCircle.x,centerCircle.y,centerCircle.radius); // For visualizing collision shapes.
shapeRenderer.circle(rightCircle.x,rightCircle.y,rightCircle.radius); // For visualizing collision shapes.
shapeRenderer.circle(leftCircle.x,leftCircle.y,leftCircle.radius); // For visualizing collision shapes.

shapeRenderer.setColor(Color.BLACK); // For visualizing touch shapes.
shapeRenderer.circle(myTouch.x, myTouch.y, myTouch.radius); // for visualizing touches.

shapeRenderer.end(); // For visualizing collision shapes.

You can look at the full source code in the link above if that makes it clearer, but the key thing to focus on here is that I now have 4 circles drawn on the screen. The “myTouch” circle is always black, and the three other circles are chosen by the variable “colorChanger”. This was added as a nice “touch” so you could see them change color when clicked. (Bad pun intended.)

So, how do we register the touches? Like so, also under render:

if (Gdx.input.isTouched()) {

/*
* Here is the interesting part. This should be:
* myTouch.set(Gdx.input.getX(), Gdx.input.getY(), 10);
* But then our touches turn out correct for X, but backwards for Y.
* Try it both ways to see the difference.
*
* Note that this is in portrait mode. It may not be that way in landscape mode.
*/
myTouch.set(Gdx.input.getX(), Gdx.graphics.getHeight() – Gdx.input.getY(), 10);

Gdx.app.log(“WJH touchpoint”, String.valueOf(myTouch)); // Write down for logging/testing.

// Did we have an overlap of the “myTouch” and a circle?
if (Intersector.overlaps(myTouch, centerCircle) ||
Intersector.overlaps(myTouch, rightCircle) ||
Intersector.overlaps(myTouch, leftCircle)) {

if (colorChanger < 2) {
colorChanger++;
} else {
colorChanger = 0;
} // If we have an overlap, then change the color.
}

} else {

myTouch.set(0, 0, 0); // If not touched, let’s move it out of the way.

} // End input detection.

According to this, if you are touching the screen, it will take input from your x/y coordinates. If you are not touching the screen, the size and position of your “myTouch” circle becomes 0.

When you are touching the screen, the myTouch circle is compared to the other circles for an overlapping condition. If they do overlap, the colorChanger is changed, so that the color of the circles can change.

If you download the apk and give it a try, you will see that you can drag a little black dot around the screen, and when you “bump” into or “cross over” the three large circles, they will change color. Pretty spiffy, huh?

Linux – keep it simple.

Take out the papers and the trash….

Every now and then I do something that I shouldn’t. Okay, probably more often than that. Either way, I really shouldn’t open up a file explorer as root, and I REALLY shouldn’t “delete” stuff while in an open file explorer as root. The reason that you shouldn’t do that is because file explorers don’t actually “delete” things. They put them in the trash. This gets doubly complicated when you use sudo to open your file explorer, because then the root “trash” ends up in your home trash.

That’s really annoying because when you right click the trash can and choose “empty”, you get an ugly pop up window explaining why you don’t have permission to empty your own garbage.

What’s worse, if you sudo open your file explorer again, you can’t get to the trash, because it is not a “real place”. Opening trash:/// in your file explorer just brings up more ugly pop up windows.

Fortunately, the answer is easy.

$ cd ~/.local/share/Trash/

Now you are in your trash can. If you look into your ./files/ folder, you will see the culprits. So, the simple thing to do is:

$ sudo chown -Rv <yourusername>:<yourusername> ./files/

or sudo chown -Rv alaskalinuxuser:alaskalinuxuser ./files/ in my case.

Now all the files in your trash can have been modified to be yours. Yes, now it is your mess to clean up, and to take out the trash you can once again right click on the trash can and say “empty”.

Linux – keep it simple.

Installing the latest PicoLisp on Ubuntu

While testing out The Quiet Learner‘s game, Dr. Theobold, a text based adventure game written in picolisp, I ran into several issues. As discussed previously, I added these issues to the bug tracker on Savannah. Come to find out, the distributed packages for Ubuntu are using version 15.xxx of picolisp, and The Quiet Learner wrote his program for version 16+. We needed to find out if the old version was the culprit, or if there truly were issues in the game.

So, I updated to version 17.7.6 (a rather interesting numbering, since I tried this the 4th of July week, but that is something else entirely).

As simple as the above statement was, my trek was not quite as simple. I am used to compiling programs. Typically, you start by unzipping the source, using ./configure, then make, and sudo make install. However, this was different.

Of course, I downloaded the source from the link in the PicoLisp Wiki. After that, I unzipped it with the standard

$ tar -xzvf ./picoLisp.tgz

and moved into the new director with

$ cd picoLisp

Once there my usual bag of tricks didn’t work, which is why it is always good to read the instructions. Ends up that I needed to cd into the src64 directory and run make. No ./configure first.

$ cd src64

$ make

And there was no option to make install. Instead I had to manually symbolically link the files, and that is where everything went wrong. You see, the INSTALL file had pre-typed instructions with all 3 links you could use, like so:

# ln -s /<installdir> /usr/lib/picolisp
# ln -s /usr/lib/picolisp/bin/picolisp /usr/bin
# ln -s /usr/lib/picolisp/bin/pil /usr/bin

But after doing that, it didn’t work. It didn’t work because I forgot that the directory was picoLisp, not picolisp. I chased my tail for a while, re-creating the same bad links over and over again until I realized my mistake. Since /<installdir> was not the directory (obviously) I was hand typing picolisp, and it wasn’t working. So, be smart and not like me. Do as I now say, not as I erroneously did!

After straightening it out, it worked great! Actually it cleared up 3 of the issues that I put on the tracker for the Dr. Theobold game. I guess it pays to have the latest and the greatest when it comes to PicoLisp!

Linux – keep it simple.

Using Savanna’s bug tracker

Creating open source apps for Android led me to become intimately familiar with GitHub and the GitHub issue tracker system. However, today I had the opportunity to try out Savannah’s bug tracking system.

I was testing out a great text adventure game by The Quiet Learner called Dr. Theobold. It’s a great game about an eccentric doctor upon whose house you enter. Inside are a multitude of quirky furnishings and numerous puzzles that you must use or figure out to progress through the game. It is reminisce of Shadow Gate intermingled with a collection of puzzle games from a brain training book, without the torches! I highly recommend that you give it a try.

However, the game is still in development, and does have a few bugs. I’ve enjoyed helping the developer by simply playing the game, and noting any peculiarities, crashes, or faults. You can see a list of the write ups here:

https://savannah.nongnu.org/bugs/?group=dr-theobold

savanah3

Overall, the issue tracker for Savannah seems to be functional, but lacks a lot of the “luster” and “polish” of the GitHub issue tracker. Aesthetics aside, it seems to function well enough. A couple of things I feel were missing, however, were the ability to categorize the issues. It assumes all issues were bugs. I tried every drop down box, there seemed to be no place for submitting issues that were “enhancements” or “feature requests” like you see on GitHub. Perhaps I was not using it properly, like I said, this was my first time using it.

Other than that, the ability to quickly attach files and give them comments was a nice feature. I could see using that to handle a visual game, by having screen shots of graphical problems. Either way, it was very straight forward and functioned great in that it did it’s intended purpose: tell the developer that I have submitted an issue, and provide a way to track that issue until it is completed/fixed.

Linux – keep it simple.

MechDome reaches out to open source app developers

MechDome, the new way to convert your Android application into an iOS app. While still somewhat in development, MechDome has been making great strides in the field of app converters. The best part is that MechDome doesn’t use your app source code, it uses your completed Android apk file to churn out a completed iOS application!

If you are interested in knowing more about the process involved in converting your Android app into an iOS one, you should read my previous article, where I gave it a go. I have to admit, it worked out rather nicely! I’ve converted two applications on their website, and so far, both worked great in the simulator!

Yesterday, MechDome sent out a newsletter informing everyone that they are starting an open source developer program! As an open source developer, I get really excited when I see companies supporting open source work. If you read my previous article, you can see where I made a few suggestions to MechDome in regards to open source development. Here’s a quote from that article:

  • Ideal: Give users the opportunity to create an open source developer account that can convert a limited number of open source apps per month, such as two or three, for free. No subscription costs, and if the account stays active, then it will not expire.

  • Less than ideal, but still helpful: Give users who already have paid subscriptions the ability to convert open source applications without counting against their monthly quota or subscription.

  • A one time setup cost: Another option might be a one time cost, rather than a subscription, for an open source account. E.g., a $25 setup fee for open source users to set up a developer account.

Based on their letter, it looks like they chose a slightly different direction, or perhaps a “modified” version of my third option. They decided on a flat fee of $25 to allow you to convert one open source app.

mechdomeopensource2

I think that MechDome is on the right track. I do appreciate how they are reaching out to open source developers, and although a one time fee per app of $25 isn’t free, it isn’t ridiculous, either. I could see how larger, community driven projects, or ones that accept donations might be able to foot the bill for app conversion, it just is not as convenient for small timers like me. I guess we will just have to wait and see.

Linux – keep it simple.

libGDX music and sound fail….

While finishing my Android app developer course, I ran into this error during game development:

[CODE]

——— beginning of crash
06-09 13:01:19.410 30345-30366/? E/AndroidRuntime: FATAL EXCEPTION: GLThread 758
Process: com.alaskalinuxuser.criticalvelocity, PID: 30345
com.badlogic.gdx.utils.GdxRuntimeException: Error loading audio file: data/spblk.mp3
Note: Internal audio files must be placed in the assets directory.
at com.badlogic.gdx.backends.android.AndroidAudio.newMusic(AndroidAudio.java:120)
at com.alaskalinuxuser.criticalvelocity.criticalvelocity.create(criticalvelocity.java:55)
at com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphics.java:275)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1532)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1259)
Caused by: java.io.FileNotFoundException: data/spblk.mp3
at android.content.res.AssetManager.openAssetFd(Native Method)
at android.content.res.AssetManager.openFd(AssetManager.java:363)
at com.badlogic.gdx.backends.android.AndroidFileHandle.getAssetFileDescriptor(AndroidFileHandle.java:237)
at com.badlogic.gdx.backends.android.AndroidAudio.newMusic(AndroidAudio.java:110)
at com.alaskalinuxuser.criticalvelocity.criticalvelocity.create(criticalvelocity.java:55)
at com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphics.java:275)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1532)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1259)

[/CODE]

It took a long time to figure out the issue, so I thought I would try to save someone else the trouble.

It hinges on this line from the libGDX wiki example:

Music music = Gdx.audio.newMusic(Gdx.files.internal(“data/mymusic.mp3”));

Which my line looked like this:

bgMusic = Gdx.audio.newMusic(Gdx.files.internal(“data/spblk.mp3”));

Should work right? But it didn’t. I had to change my line to this to make it work:

bgMusic = Gdx.audio.newMusic(Gdx.files.internal(“spblk.mp3”));

And put the mp3 file in the “assets” folder.

Hopefully, this will save someone else a really long, frustrating search!

Linux – keep it simple.

error: use of undeclared identifier ‘LED_ADJUSTMENT_G’

After synching my source with AOKP for Nougat 7.1.2, I ran into this error when trying to build for the JFLTETMO:

[CODE]
target thumb C: lights.MSM8960 <= hardware/samsung/liblights/lights.c
hardware/samsung/liblights/lights.c:215:40: error: use of undeclared identifier ‘LED_ADJUSTMENT_R’
int red = ((color >> 16) & 0xFF) * LED_ADJUSTMENT_R;
^
hardware/samsung/liblights/lights.c:216:41: error: use of undeclared identifier ‘LED_ADJUSTMENT_G’
int green = ((color >> 8) & 0xFF) * LED_ADJUSTMENT_G;
^
hardware/samsung/liblights/lights.c:217:33: error: use of undeclared identifier ‘LED_ADJUSTMENT_B’
int blue = (color & 0xFF) * LED_ADJUSTMENT_B;
^
hardware/samsung/liblights/lights.c:258:31: error: use of undeclared identifier ‘LED_BRIGHTNESS_BATTERY’
adjusted_brightness = LED_BRIGHTNESS_BATTERY;
^
hardware/samsung/liblights/lights.c:261:31: error: use of undeclared identifier ‘LED_BRIGHTNESS_NOTIFICATION’
adjusted_brightness = LED_BRIGHTNESS_NOTIFICATION;
^
hardware/samsung/liblights/lights.c:264:31: error: use of undeclared identifier ‘LED_BRIGHTNESS_ATTENTION’
adjusted_brightness = LED_BRIGHTNESS_ATTENTION;
^
6 errors generated.
[/CODE]

Pretty simple, as we have talked about this before. In the past, I actually removed these lines from the light.c file, but this time I decided I would leave them in, and declare them instead. Essentially, the outcome is the same though for this build.

What these lines do is allow for custom liblight configurations. Perhaps a particular phone or tablet has a built in LED notification light where the green is brighter than the red or blue. In that case, every mixed color made from those LEDs will look strange. This gives the rom maker the option to “dim” down one or all three of the lights. The same applies for the brightness of the battery, notification, or attention lights.

As you can see below, I just declared them with the default values:

[CODE]
return err;
}

// WJH declaring these undeclared lights.
int LED_ADJUSTMENT_R = 1;
int LED_ADJUSTMENT_G = 1;
int LED_ADJUSTMENT_B = 1;
// WJH declaring these undeclared lights.

static int calibrate_color(int color, int brightness)
{
int red = ((color >> 16) & 0xFF) * LED_ADJUSTMENT_R;
int green = ((color >> 8) & 0xFF) * LED_ADJUSTMENT_G;
int blue = (color & 0xFF) * LED_ADJUSTMENT_B;

return (((red * brightness) / 255) << 16) + (((green * brightness) / 255) << 8) + ((blue * brightness) / 255);
}

…………EDITED FOR SPACE………………

led->delay_off = state->flashOffMS;
break;
default:
return -EINVAL;
}

// WJH declaring these brightness adjustments.
int LED_BRIGHTNESS_BATTERY = 255;
int LED_BRIGHTNESS_NOTIFICATION = 255;
int LED_BRIGHTNESS_ATTENTION = 255;
// WJH declaring these brightness adjustments.

switch (type) {
case TYPE_BATTERY:
adjusted_brightness = LED_BRIGHTNESS_BATTERY;
break;
case TYPE_NOTIFICATION:
adjusted_brightness = LED_BRIGHTNESS_NOTIFICATION;
break;
case TYPE_ATTENTION:
adjusted_brightness = LED_BRIGHTNESS_ATTENTION;
break;
default:
adjusted_brightness = 255;
}
[/CODE]

 

For the LED_ADJUSTMENT_R/G/B, I gave a value of 1. If you look at the math, it is used in the next formulae as (a & b) * LED_ADJUSTMENT_R/G/B. So if I set a value of 0, then the mathmatical outcome will be 0. If I set it at 1, then it will always be (a & b).

For the LED_BRIGHTNESS_BATTERY and so forth, I used the adjusted_brightness of 255, which is the default.

For both of these sets, I could have just removed them all together. But I build for several phones using the same source. By leaving them in, I should have an error if the device tree declared what is already declared in the lights.c file. Or at least that is my hope. In that case, then I could remove my handy work to make room for the actual values.

Linux – keep it simple.

LG G4 on SlimRoms: delete the pin key in TWRP!

In my last post, I told the epic adventure of figuring out how to get into recovery mode so I could fix my unbooting phone. I had performed a backup of SlimRoms before trying to flash OmniRom, and since I was back into TWRP, I restored my backup. Figuring all was well, I rebooted.

Everything booted up great. However, once into the rom, it asked for my screen lock pin, as usual. But unlike the normal response, it kept saying that I was entering the wrong pin. I tried my pin, my old pin, and no pin. No luck. It wasn’t working.

There are a lot of articles on this, and this will not be much new, however, the names of my lock files were different than the article I read, so I am posting the names of the files here in case I forget when this happens to me again. (Most of this blog is simply my own scratchpad of notes to help me remember something….)

So, power off the phone, and jump back into TWRP (see the previous post if you need help with that). In TWRP, go to Advanced – > File Manager.

Scroll down to the /data folder. Open the /system folder and look at the contents.

On my phone I had to delete these files to disable the lock:

gatekeeper.password.key

gatekeeper.pattern.key

locksettings.db

locksettings.db-shm

locksettings.db-wal

After deleting these five files in the TWRP file manager, I then rebooted the phone. Sure enough, now I had no lock screen settings nor pin in the ROM. Back in action! I, of course, immediately set up a new lock screen and pin for security purposes. Hopefully that helps you too!

Linux – keep it simple.