use BUILD_PREBUILT instead!

OmniRoms Nougat. An elusive dream of mine is building OmniRoms for my devices. In the past I just couldn’t seem to get them to work. Well, I have decided to give it another go, and here was one of my first errors:

[CODE]
build/core/Makefile:34: *** Prebuilt apk found in PRODUCT_COPY_FILES: vendor/lge/g4-common/proprietary/priv-app/qcrilmsgtunnel/qcrilmsgtunnel.apk:system/priv-app/qcrilmsgtunnel/qcrilmsgtunnel.apk, use BUILD_PREBUILT instead!.
[/CODE]

So, I took a look at g4-common-vendor-blobs.mk:

[CODE]
vendor/lge/g4-common/proprietary/lib/libloc_ds_api.so:system/lib/libloc_ds_api.so \
vendor/lge/g4-common/proprietary/lib/libalhdri.so:system/lib/libalhdri.so \
vendor/lge/g4-common/proprietary/priv-app/qcrilmsgtunnel/qcrilmsgtunnel.apk:system/priv-app/qcrilmsgtunnel/qcrilmsgtunnel.apk \
vendor/lge/g4-common/proprietary/vendor/firmware/libpn547_fw_C9.so:system/vendor/firmware/libpn547_fw_C9.so \
vendor/lge/g4-common/proprietary/vendor/firmware/BCM4335_003.001.009.0117.0620_LGE_P1_EU.hcd:system/vendor/firmware/BCM43…..
[/CODE]

Here we can see that the file in question “qcrilmsgtunnel.apk” is being copied over with the vendor blobs. The error is telling us that we need to install it as a prebuilt app, instead of copying the app over as a normal file. So, I edited out that line in the g4-common-vendor-blobs.mk file, and edited g4-common-vendor.mk by adding it like so:

[CODE]
PRODUCT_PACKAGES += \
qcrilmsgtunnel \
qcnvitems \
qcrilhook
[/CODE]

Notice that I did not move the apk file around, just redefined how to get it moved into the rom. Well, that took care of that error! 1 down, untold dozens to go!

Linux – keep it simple.

 

Critical Velocity – an open source libGDX game that was crashing on small screens is now fixed!

Critical Velocity is a fun little open source arcade style scrolling game that I made after finishing my Android developer class. It was my first released game using the libGDX engine, an open source graphics engine that is great for making games. Due to my inexperience, however, I didn’t take into account that all screens are not created equal. Some screens are bigger than others, and some have lower resolution than the phone I built the game on.

This caused a problem. After releasing the game, I quickly was alerted to the issue through the GitHub issue tracker, where several players let me know that it was crashing on startup with their phones. It took a little bit of time to figure out, but I came to realize that the app was crashing on phones that were smaller than 800×480 screen resolution.

At first I thought there were all sorts of problems with graphic asset sizes, and memory issues. I tried numerous things to fix it, but nothing worked. Finally, I gave up. But, a few days ago, I decided to take another look. By God’s grace, this time I got it figured out! Before, I was working off of the information provided by people with smaller resolution screens, but I decided that I should load up the game in an emulator with a 320×240 resolution screen, and watch the logs. That’s when I found the problem.

The issue didn’t have anything to do with libGDX, the graphic assets, or the amount of memory the game takes (about 15 MB). As it turns out, the math just didn’t add up. Literally!

In the game, the upper and lower walls are separated by a gap. The size of the screen and the size of the gap is used to determine where the next set of walls opening can be (up or down) from the previous wall. The idea was that as you went faster, an opening at the top of the screen followed by an opening at the bottom of the screen is technically impossible to reach, so this math would keep it “near” the other opening within reason, but still allow it to be randomly placed, up or down from the previous one.

The math looked like this:

Place of the next wall opening = randomly based off of (1/2 of the screen height – the size of the gap) from the center of the screen.

This worked great on my test phone that had a screen resolution of 1920×1080. With the standard gap that I set of 450, the math looked like this:

Place of the next wall opening = randomly based off of (960 – 450 = 510) from the center of the screen.

But it didn’t work for a screen as small as 320×240 because:

Place of the next wall opening = randomly based off of (160 – 450 = -290) from the center of the screen.

For a random number, you can have a negative outcome, but you cannot put in a negative input. The random number is based on starting at 0, and create UP TO X random numbers. So if X is negative, then the random number generator doesn’t know what to do!

So I had to invent a way to fix this problem. Fortunately, that was easy. I used an if/then statement to ask what the screen size was, and then changed the gap size to be less than 1/2 of the screen size. I also had to edit a few parameters, such as thrust, speed, and distance also based on screen size. You can check out my code and commits here and here, if you’d like.

Long story short: Don’t make assumptions, check the logs and they WILL lead right to the problem! If I had run the emulator myself before, not having a small screen phone anymore, I hopefully would have seen this right away. Here are some screen shots of the game on different phones. Unfortunately, I still have a lot to learn to make sure that the game LOOKS the same on different sized screens, but at least now it doesn’t crash!

Linux – keep it simple.

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.