Category: Java

Android – Creating a simple hamburger menu in title bar

What we want:

A standard hamburger style menu that can be used in the active title bar of an Android Application

Android hamburger menu collapsed

Android hamburger menu collapsed

How to do it:

Create a menu layout in the menu directory of the res folder, reference it in your activity, and program functionality to each menu item.

Menu-item file:

If the folder “menu” doesn’t exist in “res”. You will need to create it. See below:

Android resource menu layout

Android resource menu layout

Contents of new file:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/iconHamburger"
        android:icon="@drawable/hamburger"
        app:showAsAction="ifRoom|withText"
        android:title="Other">
        <menu>
            <item
                android:icon="@drawable/settingsicon"
                android:id="@+id/menuItemSettingsicon"
                android:onClick="launchSettings"
                android:title="Settings"></item>
            <item
                android:icon="@drawable/browser"
                android:id="@+id/menuItemWebsite"
                android:onClick="launchBrowser"
                android:title="Website / Status"></item>
            <item
                android:icon="@drawable/bug"
                android:id="@+id/menuItemBugReporting"
                android:onClick="launchEmail"
                android:title="Bug reporting"></item>
            <item
                android:icon="@drawable/beer"
                android:id="@+id/menuItemBeer"
                android:onClick="launchDonateActivity"
                android:title="Donate / Buy me a beer"></item>

        </menu>

    </item>
</menu>

You’ll need a hamburger icon, which you can obtain off google images anywhere. I also have icons on each menu item. The end result looks like this:

Android hamburger menu expanded

Android hamburger menu expanded

We’ll need to make the hamburger expand on click, so create the following method

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

 

You’ll notice that in the XML file, I have an onClick property that refers to a method we haven’t implemented in this java file. We’ll add the methods to the file now (The method will need to accept a Menu item!)

    public void launchEmail(MenuItem menuItem)
    {
        //do whatever you want in this method
        Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
        emailIntent.setType("message/rfc822");
        emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] {"[email protected]"});
        try {
            emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Hi, I found a bug with your app -");
            startActivity(emailIntent);
        } catch (ActivityNotFoundException e) {
            Toast.makeText(getApplicationContext(), "You have no email client installed! Email me at samp[email protected]", Toast.LENGTH_LONG).show();
        }

    }

 

That’s it! That’s how you create a very simple Hamburger menu!

Android Studio – How to make an instance of Context during unit testing

One of the great new features of Android Studio 2.0 is the automatic implementation of unit testing when you create a new project. However, in it’s base form, it’s only good for testing Java code (nothing Android specific). Mocking an instance of Context won’t do any good if you need it to execute your code.

The solution is…

 Robolectric

The only drawback to this method, is that it doesn’t currently support Api level 22 and above. You will need to adjust the following in your build.gradle…

compileSdkVersion 21
buildToolsVersion "21.1.2"

You will also need to change the version of appcompat you’re using

compile 'com.android.support:appcompat-v7:21.0.0'

Add the following line into the dependencies section

testCompile "org.robolectric:robolectric:3.0"

So all said and done, your build.gradle file should look similar to this

apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "net.evanp.umactuallynerdtriviagame"
        minSdkVersion 15
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    testCompile "org.robolectric:robolectric:3.0"
    compile 'com.android.support:appcompat-v7:21.0.0'
}

 

Editing your test classes

Before your class is declared, add the following

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class)

On top of the test method add @test just like usual, but notice how the instance of Context is created

@Test
public void testAbilityToAccessXML() throws Exception {
    Context context = RuntimeEnvironment.application.getApplicationContext();
    ProgramWideFunctions.randomCategory(context);
}

It’s that easy!

Implementing a hierarchy (tree like) structure with Java / Android and navigating them with Buttons

For my Canadian Classifieds Alerter app, I needed to implement a hierarchy like structure to represent locations and categories. This is what I used in my solution.

For example,

Buy N’ Sell -> Computers -> Laptops

Canada -> New Brunswick -> Moncton

Laptops belongs to Computers, which a sub category of Buy N’ Sell’

Moncton belongs to New Brunswick, which belongs to Canada

Solution

Here it is in it’s simplest form. We’ll actually make it do something further down.

public enum KijijiCategory {
    //root category
    CATEGORY(null),
    //buy n sell, pass in the root category as the parent
    BUY_N_SELL(CATEGORY),
    //Pass in Buy N Sell as the parent category
    COMPUTERS(BUY_N_SELL),
    //Pass in Computers as the parent category
    LAPTOPS(COMPUTERS),
   

    private KijijiCategory parent = null;
   

	//Constructor, you pass in the parent
    KijijiCategory(KijijiCategory parent) {
        this.parent = parent;
    }

}

General explanation of what’s going on:

For CATEGORY, there is no parent, so I pass in null.

For BUY_N_SELL, the parent is CATEGORY, so I pass it in

For COMPUTERS, the parent is BUY_N_SELL, so I pass it in.

For LAPTOPS, the parent is COMPUTERS, so I pass it in.

Are you starting to see where this is going?

What can we use it for?

Check out this video.

Notice how easy it is to traverse through menu options? To do this we’re going to have to add more to the code I posted above

public enum KijijiCategory {
    //root category
    CATEGORY(null),
    //buy n sell, pass in the root category as the parent
    BUY_N_SELL(CATEGORY, 10, "Buy n sell"),
    //Pass in Buy N Sell as the parent category
    COMPUTERS(BUY_N_SELL, 16, "Computers"),
    //Pass in Computers as the parent category
    LAPTOPS(COMPUTERS,773, "Laptops"),
   
	
    private KijijiCategory parent = null;
    //unique identifier used internally by my app, you might not
	//need this or you may need to add your own
	private int id;
	//title will give us a nicer looking 
    private String title = "";


	//In this example
    KijijiCategory(KijijiCategory parent) {
        this.parent = parent;
    }

	//This is the constructor used by almost all of the categories above
    KijijiCategory(KijijiCategory parent, int id, String title) {
        this.parent = parent;
        this.id = id;
        this.title = title;
    }

    /*
     * Getters
      * */
    public String getTitle() {
        return this.title;

    }

    public String getParentName() {

        if (parent == null)
        {
            return "none";
        } else {
            return parent.getTitle();
        }
    }

    public KijijiCategory getParentCategory() {
        return parent;
    }

    public int getId() {
        return this.id;
    }

    @Override
    public String toString() {
        return "Kijiji Category name of: " + this.getTitle() + " and id of " + this.getId() + " and a parent of " + getParentName();
    }
}

You’ll notice I added a new constructor. I’m passing in an internally used identifier, and a nicer to look at string called title we’ll use to set the text for the boxes. I also added a few getters and overrode the toString() method

This is how I generated the LinearLayout

First step is to call the new method in onCreate (I prefer to keep this stuff out of onCreate as it makes future modifications easier)

generateKijijiCategories(KijijiCategory.CATEGORY, categoryLayout);

Here is where all the buttons are generated.

private LinearLayout generateKijijiCategories(final KijijiCategory categoryParent, final LinearLayout categoryLayout) {

        //Shows all of the buttons if we're on the main category 

        if (categoryParent == KijijiCategory.CATEGORY) {
            final Button button = new Button(this);
            button.setText("All Categories");
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    button.setTextColor(Color.GREEN);
                    categoryToQuery = KijijiCategory.CATEGORY;
                }
            });
            categoryLayout.addView(button);

        }
        //iterate through all potential values
        for (final KijijiCategory kijijiCategory : KijijiCategory.values()) {
            //abandon the current iteration if it's not a child of the parent we passed in
	    if (kijijiCategory.getParentCategory() != categoryParent) {
                continue;
            }
	    //Instantiate a button
            final Button button = new Button(this);
	//Give it a nice looking text
            button.setText(kijijiCategory.getTitle());
			//Used internally in my app
            button.setId(kijijiCategory.getId());
			button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
		    //turns focus to the top
                    txtCategories.requestFocus();
		    //empty out all buttons
                    categoryLayout.removeAllViews();
                    button.setTextColor(Color.GREEN);
                    categoryLayout.addView(button);
                    categoryToQuery = kijijiCategory;
		    //This isn't true recursion, it's debateable though
                    generateKijijiCategories(kijijiCategory, categoryLayout);

                }
            });
			//add the button to the layout
            categoryLayout.addView(button);
        }
        //add back button!
        if (categoryParent != KijijiCategory.CATEGORY)
        {

            Button backButton = new Button(this);
            final Button parentButton = new Button(this);
            parentButton.setText(categoryParent.getParentCategory().getTitle());
            parentButton.setTextColor(Color.GREEN);
            backButton.setText("Back");
            backButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    txtCategories.requestFocus();
                    categoryLayout.removeAllViews();

                    if(categoryParent.getParentCategory() != KijijiCategory.CATEGORY) {
                        categoryLayout.addView(parentButton);
                    }
                    categoryToQuery = categoryParent.getParentCategory();
                    generateKijijiCategories(categoryToQuery, categoryLayout);
                }
            });
            categoryLayout.addView(backButton);
        }

        return categoryLayout;
    }

See not so bad!

How to get instant alerts from Kijiji – Canadian Classifieds Alerter

You’ve tried using Kijiji’s daily alerts. The issue with them… is that they come daily. As in once a day, when everyone else gets them, meaning you have no more advantage than anyone else. The worst part is… sometimes they don’t even get sent at all.

The solution

If you have an Android device, you can download “Canadian Classifieds Alerter” from the google play store.

Or you can download the iPhone/iOS version on the Apple Store

What does it do?

Canadian Classifieds Alerter checks Kijiji for you! Let’s say you are looking for an iPhone and you’re on a budget of $200. Simply set an alert to check for “iPhone” and a price limit of $200 and you will be notified the next time someone posts it on Kijiji… before anyone else!

Where can I get it and does it cost money?

It is available on Google play and the Apple app store for the low cost of FREE!

How do I setup an alert?

(These steps are for an outdated Android version, iOS/iPhone version and newer Android versions will be very similar!)

Glad you asked and that you’re on board. Let’s walk through the steps… I am going to assume you know to download an application from Google Play or Amazon. Because of how their search is setup, you may have to search for “Canadian Classifieds Alerter” all in quotes. If not, just click this link for Google Play or this link for Amazon on your Android smartphone/tablet.

(These screenshots are from an earlier version of the app. The steps are still the same)

Step 1. Click “New Alert”

The New Alert screen will then be displayed

Click on "New Alert"

Click on “New Alert”

 

Step 2. Select a Category and Location

Clicking through the buttons will traverse you through categories, and categories within categories. The same goes for location. For this example, I am picking “Cellphones” in the “Phones” category and I will be searching in Moncton, New Brunswick. If you make a mistake, don’t sweat it, just press the back button.

step2

 

Step 3. (Optional) Enter a search query and a maximum price

While this part is optional, I highly recommend it just so you aren’t bombarded with notifications with things you don’t care about, or things out of your price range. In the maximum  price field, enter the most you’re willing to pay (ie, 200) and enter a search query in the “Search for” box (In this case, “iphone”).

step3

Step 4. Press “ADD ALERT”

Self-explanatory.

step4

And just like that you’re brought to the main screen and your notification is now there

step5

Step 5. Close the application and wait.

There is a background service running that does all the checking for you… sit tight. The more specific your search is, the less results you get. It’s worth mentioning that by default, it will not check unless you’re on wifi. Go into the settings to change this. Want a rundown of all the settings? Check out my blog post on how to do that!

Step 6. You got an alert! Hurry and jump on it!

step6

Wow, that was fast! Touch the notification and the Notifications screen will appear… click “GO TO AD” to open the ad in your browser

 

step7

Check the ad out, if you like it, then contact the seller!

step8

 

Want more information? Check out these posts:

Canadian Classifieds Alerter – How to customize and configure to your liking – Rundown of the app settings
Canadian Classifieds Alerter –  Frequently Asked Questions (FAQ)