Having trouble building Bluefruit LE app in Android Studio?

While playing with my Bluefruit Feather, I decided to build the Android app straight from the source code, so I could see the ins and outs of how it works. Unfortunately, when I downloaded the source code and loaded it into Android Studio, I noticed that it didn’t compile the gradle files correctly.

Turns out that they updated the gradle files for Android Studio 3. My Linux distribution was still using Android Studio 2.3.3. That may see pretty out of date, but it went from 2.3 straight to 3.0.

So, I had two choices, update my Android Studio manually, or downgrade the Bluefruit LE app. Fortunately, Github allows you to view a repository at a previous commit level. So, I loaded up the commit just before they updated the gradle files, and downloaded the repository at that state. I figured if you are reading this, you might want that too, so here is a direct link:

https://github.com/adafruit/Bluefruit_LE_Connect_Android/tree/175d517b3e964a2862f311c75bea740075cafe05

bluefruit_le

Downloaded, unzipped, loaded with Android Studio 2.3.3, and ta-da! It worked! I like easy problems. In the future, however, I will need to update my Android Studio anyways, but for now, this gets me where I need to be. Perhaps by the time I need to update, the Linux version I am using will have that package available pre-built.

Linux – keep it simple.

Advertisements

Android Studio emulator stopped launching after upgrade in Ubuntu 16

I don’t usually re-post something that someone else figured out, but it took me a long time to figure this out, so I thought I would share here.

The problem I had was relating to Android Studio and the emulator. I was using the emulator to test out various programs that I was working on, but it stopped working after an update. I didn’t realize it right away, as I often use my actual cell phone, rather than the emulator. I find that I can tap faster with my finger than I can click with the mouse.

Either way, some time after I did an update, I decided to use the emulator. Unfortunately it didn’t work. Not only did it not work, there were no errors. I actually had no idea of why it stopped functioning. Thus started my search for an answer. I tried just about everything before finding the right answer.

The first thing I tried was deleting and remaking a device with the AVD. Still no luck. Other people were suggesting that I move my entire Android Studio folder into the SDK folder. That didn’t work either.

Still others were deleting the AVD folder and then creating new emulators. This still was not the solution. Finally, though, I found a solution that worked:

$ cd ~/Android/Sdk/emulator/lib64/libstdc++/
$ mv libstdc++.so.6 libstdc++.so.6.bak
$ mv libstdc++.so.6.0.18 libstdc++.so.6.0.18.bak
$ ln -sf /usr/lib/x86_64-linux-gnu/libstdc++.so.6 ~/Android/Sdk/emulator/lib64/libstdc++/libstdc++.so.6
$ ln -sf /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22 ~/Android/Sdk/emulator/lib64/libstdc++/libstdc++.so.6.0.22

Lest that you think I came up with this on my own, I didn’t. I found it here on Stack Overflow, by user Martin Revert. How he came to this conclusion is beyond me, but I’m glad that he shared it, because it was just what I needed!

Hopefully, that will save someone from trying everything under the sun to fix this problem.

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.

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.

Setting up libGDX for Android Studio on Ubuntu

Every one else is probably brighter than me. However, after reading the instructions over and over again, and then attempting to follow them, it just wasn’t working. All I wanted to do was start a libGDX project in Android Studio. I finally figured out where I went wrong, so here is the step by step for any one else that gets stuck like I did. Please read all the instructions first, because step 5 becomes step 1, but doesn’t make sense unless you read them in this order:

  1. Go to https://libgdx.badlogicgames.com/download.html and click “Download Setup App”.
  2. A jar is downloaded. Don’t try to import it, or something of that nature. Clicking on it is no good either. Simply open a terminal window and cd to the Downloads directory. Once you are there, type: $ java -jar ./gdx-setup.jar
  3. A window will pop up. Fill in the usual blanks to name your app.
  4. For the Android SDK field, open Android Studio, and click File –> Project Structure. That first field is the Android SDK.
  5. For the folder to put the newly created app in, be sure that you choose a folder that is empty, because it will wipe out everything in that folder. So I recommend you make a folder for it first!
  6. Uncheck the things you don’t need, like IOS, HTML, etc, and click generate.
  7. Once it is done, go back to Android Studio, and click File –> open.
  8. Choose the folder you put it in, and Android Studio will recognize the gradle files in it, and open your new app!

Hopefully that makes sense and keeps you from wasting as much time as I did. Most of you are probabl smart enough to know this already!

Linux – keep it simple.

Critical Velocity! A fun side scrolling arcade style game.

After finishing my Android developer course, I decided to try to put my new found (fledgling) skills to use by making a game. It’s a classic side scroller with an arcade feel to it. The story line is pretty short and to the point: you are a captain of a space ship that must escape a tunnel buried beneath the surface of a collapsing planet.

As you pass each object in the tunnel, you gain speed. There are power ups and bonus points, all the usual suspects in arcade game play, so be sure to check it out in my “Homemade Apps” section, on the play store, or in my github (it is licensed under the Apache 2.0 open source license.)

The background for the game was provided by the Quiet Learner ( https://qlfiles.net/ ), the music is “Space Blockbuster” by Soulbringer ( http://freemusicarchive.org/music/Soulbringer/Soulbringer/Soulbringer_-_Space_Blockbuster ), and the graphics were modified from Dan Cook’s work which he released to the public ( http://www.lostgarden.com/2005/03/game-post-mortem-hard-vacuum.html ). It’s great when people share their work so others can build upon it or with it. The same applies for my work on this game, if you can use it, do!

Linux – keep it simple.

Getting photos with intents on Android

During my class for app development, the instructor showed us how to get a photo from the phone’s gallery with intents. I wanted to take that one step farther, so I did. I also added getting a photo from the camera. To keep things small, I set the camera still to be returned as a thumbnail view, per the android instructions here:

https://developer.android.com/training/camera/photobasics.html

Here is what I have:

MainActivity.java

[CODE]

package com.example.alaskalinuxuser.photohowto;

import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {

    // Define our image view.
    ImageView myImage;

    @Override // On create, do this....
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Declare our image view.
        myImage = (ImageView)findViewById(R.id.imageView);

    }

    // If they click to choose a picture from the gallery....
    public void choosePic (View picView) {

        // Call the intent for the gallery.
        Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        // And start that intent for the result number 1.
        startActivityForResult(i, 1);

    }

    // If they click to take a picture button....
    public void takePic (View takeView) {

        // Call the intent for the camera.
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // And start that intent for the result number 2.
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(takePictureIntent, 2);
        }

    }

    @Override // Listen for the results from intents.
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // If it is result number 1, and it was ok, and they chose something, then...
        if (requestCode == 1 && resultCode == RESULT_OK && data != null) {

            // Get the uri.
            Uri myChosenImage = data.getData();

            // Try in case it fails.
            try {

                // Make a bitmap from the uri.
                Bitmap myBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), myChosenImage);

                // Set our chosen image to the view.
                myImage.setImageBitmap(myBitmap);

                // Give a catch in case there is a problem.
            } catch (IOException e) {
                e.printStackTrace();
            }

            // But if it is result number 2, and it is okay, and there is data, then....
        } else if (requestCode == 2 && resultCode == RESULT_OK && data != null) {

            try { // In case it fails.

                // Get the extras (a small thumbnail in this case).
                Bundle extras = data.getExtras();
                // Set our bitmap to that extra.
                Bitmap camImage = (Bitmap) extras.get("data");
                // Set our image with that bitmap.
                myImage.setImageBitmap(camImage);
                // A catch in case it fails.
            } catch (Exception e) {
                e.printStackTrace();
            }

        }


    }
}

[/CODE]

 

Pretty neat, huh? You can check this out on my GitHub under the small apps repository.

Linux – keep it simple.

WebViews for dummies like me.

In my Android Developer Course, the instructor showed us how to create webviews and dataviews. I wanted to take that one step farther, so I made this app, which can switch between a dataview and a webview. You can download it here, just click on the floating button to switch between the views:

http://www.mediafire.com/file/d8x9yc4ykn7943v/Webviewfordummieslikeme.apk

Currently, for a webview, it goes to my website, right here. For a data view, I just threw together a few lines of HTML code and slapped it in there. But, here are a few great little tidbits about the program for those who are new like me, and need help figuring out what to do.

MainActivity.java

/* Copyright 2017 by AlaskaLinuxUser (https://thealaskalinuxuser.wordpress.com)
*
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alaskalinuxuser.webviewsfordummies;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends AppCompatActivity {

// Declare your webview …
WebView myWebView;
// Declare our boolean for switching.
Boolean webViewTrue;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

// Set our boolean to true, as we are displaying a website first.
webViewTrue = true;

// To identify my webview that I am going to put the website or data on.
myWebView = (WebView)findViewById(R.id.myWebView);

// To enable javascript.
myWebView.getSettings().setJavaScriptEnabled(true);

// To keep it here in our mini webview browser
myWebView.setWebViewClient(new WebViewClient());

// To load which webpage, in this case, mine.
myWebView.loadUrl(“https://thealaskalinuxuser.wordpress.com&#8221;);

// So, by clicking on the FAB, you can swap between webview and dataview.
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, “Switched between webview and dataview.”, Snackbar.LENGTH_LONG)
.setAction(“Action”, null).show();

// If we are in webview mode.
if (webViewTrue) {

// Then switch to dataview mode.
webViewTrue = false;

// You can load any data you make, you just need data, type, and encoding.
String myEncoding = “UTF-8”;
String myType = “text/html”;
String myData = “<html><body><h1>Check this out!</h1><p>This is just demonstrating how to load your own ‘data’.</p><h2>More info!</h2><p>Feel free to test this out with some code edits.</p></body></html>”;

// And pass that to our webview.
myWebView.loadData(myData, myType, myEncoding);

// Else, if you are in dataview, switch to web view.
} else {

// Set our boolean back to true.
webViewTrue = true;

// To load which webpage, in this case, mine.
myWebView.loadUrl(“https://thealaskalinuxuser.wordpress.com&#8221;);

}

}
});
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();

//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}

return super.onOptionsItemSelected(item);
}
}
The key parts here are these:

// If we are in webview mode.
if (webViewTrue) {

// Then switch to dataview mode.
webViewTrue = false;

// You can load any data you make, you just need data, type, and encoding.
String myEncoding = “UTF-8”;
String myType = “text/html”;
String myData = “<html><body><h1>Check this out!</h1><p>This is just demonstrating how to load your own ‘data’.</p><h2>More info!</h2><p>Feel free to test this out with some code edits.</p></body></html>”;

// And pass that to our webview.
myWebView.loadData(myData, myType, myEncoding);

// Else, if you are in dataview, switch to web view.
} else {

// Set our boolean back to true.
webViewTrue = true;

// To load which webpage, in this case, mine.
myWebView.loadUrl(“https://thealaskalinuxuser.wordpress.com&#8221;);

}

If you are in a webview, it switches to a dataview, and vice versa. But the thing I wanted to point out is the use of the String variables (myEncoding, myType, myData) which here I just set statically, but you could have some app that when the user clicks something, it fills in these variables, which in turn, when you load the data, it now has some pertinent information. Just food for thought. Praise God, it even works!

Linux – keep it simple.

Using SQLlite in your Android app

So, as part of my Android Developer Course by Rob Percival (which is excellent, and I highly recommend every computer/Android geek take), he showed us how to make use of SQLlite in our Android app. In the demonstration and challenge, he was using static inputs, like this:
// And add some information to that table.
firstDatabaseEver.execSQL(“INSERT INTO events (name, year) VALUES (‘Birth’, 1985)”);

Which is great. He was just showing us how SQLlite worked. With that said, in a really useful app, I figured I would need a way to take a user’s input and put it into the table, so I fiddled around a bit, and here is what I came up with.

MainActivity.java:
/* Copyright 2017 by AlaskaLinuxUser (https://thealaskalinuxuser.wordpress.com)
*
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alaskalinuxuser.sqllitedemo;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// Let’s make some variables to use later.
String nameVar = “Joined the Navy”;
int yearVar = 2004;

try {

// First, make a database, open or create will open if exist, create if not.
SQLiteDatabase firstDatabaseEver = this.openOrCreateDatabase(“events”, MODE_PRIVATE, null);

// Now, let’s ceate a table.
firstDatabaseEver.execSQL(“CREATE TABLE IF NOT EXISTS events (name VARCHAR, year INT(4))”);

// And add some information to that table.
firstDatabaseEver.execSQL(“INSERT INTO events (name, year) VALUES (‘Birth’, 1985)”);

// And a second one for fun, this time, we will use our variable we created, you can see
// how this would be useful for an app, so you could have the user’s input dumped into a
// table.
firstDatabaseEver.execSQL(“INSERT INTO events (name, year) VALUES (‘” + nameVar + “‘, ” + yearVar + “)”);

// Now we need a cursor to retreive the data with a query.
Cursor myCursor = firstDatabaseEver.rawQuery(“SELECT * FROM events”, null);

// Now that we have the data, we need a way to index them, or grab the parts we need.
int nameIndex = myCursor.getColumnIndex(“name”);
int yearIndex = myCursor.getColumnIndex(“year”);

// Let’s start from the top of the table, by moving to the first position.
myCursor.moveToFirst();

// And if it is not null, let’s use it.
while (myCursor != null){

// Logging for posterity….
Log.i(“WJH”, myCursor.getString(nameIndex));
Log.i(“WJH”, Integer.toString(myCursor.getInt(yearIndex)));

// And move on to the next result in the table.
myCursor.moveToNext();
}
} catch (Exception e) {

e.printStackTrace();

}
}
}

Note that I don’t actually have user’s input into the table here, but I did use variables to input the data into the table, like so:

// Let’s make some variables to use later.
String nameVar = “Joined the Navy”;
int yearVar = 2004;

// And a second one for fun, this time, we will use our variable we created, you can see
// how this would be useful for an app, so you could have the user’s input dumped into a
// table.
firstDatabaseEver.execSQL(“INSERT INTO events (name, year) VALUES (‘” + nameVar + “‘, ” + yearVar + “)”);

As we can see, the input into the table of “events” is based on the output of the variables “nameVar and yearVar, which I previously defined. It is really easy to see that we could use something like getText from an editText field and input those variables into the tables. Which I think is the best use of it.

Linux – keep it simple.

Using your Open Weather Map API key

If you are reading this, you are probably trying to figure out how to use your api key from openweathermap.org. If you are reading this and don’t know what that is, don’t feel bad. I didn’t either until I started my Android Developer Course. In a nutshell, when your phone app tells you the weather, it gets it from a server somewhere in a special format, called an API, which returns a JSON object. At least, that’s how I understand it.

The problem is, that server will not just tell anyone the data. All of these servers want you to have a key. Most sites offer some sort of free plan for a very limited number of calls, particularly for developers or for personal use. This requires an account. So I got one at openweathermap, and then was given a key.

One of the principle things you need to get the api data from a provider is an api key. This is where I was having big trouble. After registering and getting the key, I then went to the guide on how to use it. It is located here if you are interested, but it didn’t work.

http://openweathermap.org/appid#get

In the guide it told me to use this call method:

http://api.openweathermap.org/data/2.5/forecast/city?id=524901&APPID=1111111111

Except with my key after APPID=, instead of the 111111111’s. The problem was, it would return this error when I made the call:

{“cod”:401, “message”: “Invalid API key. Please see http://openweathermap.org/faq#error401 for more info.”}

or sometimes this one:

“This site can’t be reached

api.openweathermap.org refused to connect.”

I was getting a little bit frustrated. I reread the documentation, and I still got bad results. I waited until the next day to make sure my calls per day were reset. Still no luck. I googled, I searched, and eventually, I got to this thread:

https://github.com/cmfcmf/OpenWeatherMap-PHP-Api/issues/46

Where I learned two really important things that made it all work:

#1. Don’t use https:// in the call, use http:// instead.

#2. Instead of APPID in the call, use appid (lowercase) in the call to get the results.

Once I did these two things, it immediately started working for me. So if you are having trouble, you should give that a try. Hopefully this will save you hours of frustration.

Linux – keep it simple.