Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 1 of 1

Thread: Android Tutorial: Shared Management of Ad-Free and Ad-Supported App Versions

  1. #1
    Forum VIP
    Join Date
    Jul 2010
    Posts
    1,676
    Thanks
    25
    Thanked 329 Times in 305 Posts

    Default Android Tutorial: Shared Management of Ad-Free and Ad-Supported App Versions

    I've had to come up with a solution for this, so I figured I would write a tutorial for anyone else who has had this problem.

    Problem:
    You have an Android App which you are ready to put on the Play Store, but you would like 2 versions of the app, one which you will charge for (usually 99 cents) and one which is free but has ads. Having two versions of the app requires you to have two separate apps, which means managing two separate code bases. Managing two separate code bases means doubling your maintenance efforts.

    Solution:
    In this tutorial, we will discuss how to reduce your maintenance efforts by using a third project as an "Android Library Project". We will be utilizing 3 projects:
    1. The Library Project (TestApp), which will contain the majority of your app's user interface.
    2. The Ad Supported App (TestAdApp), which will contain your app's user interface, with banner ads along the top of the activities.
    3. The Paid App (TestPaidApp), which will contain your app's user interface without any ads

    Requirements:
    1. Eclipse (Tutorial uses Version: 4.3.2)
    2. Installed Android Development Kit (Tutorial uses API Level: 19)
    3. Installed Android Emulator (Tutorial uses an emulator created using the AVD Manager)
    4. The Google Play Services extra installed
    5. A valid Ad Unit Id

    Setup:
    We begin by creating our three Android projects. I will gloss over this, since there are many tutorials out there to show you how to do this.
    Creating TestApp:
    1. Go to New > Other > Android > Android Application Project
    2. Enter the desired Application Name (TestApp), and change the Project Name and Package Name according to your preferences. Ensure the Minimum Required SDK is no lower than 11 (we will be using Fragments). Make the Target API 19 (or a lower API level which is still compatible). Press Next.
    3. Check the "Mark this project as a library" box and press Next
    4. Modify the icons or just press Next
    5. In the Create Activity screen, select Blank Activity with Fragment and press Next
    6. Name the new Activity (MainActivity), adjust the names of the layout and fragment layout as you see fit, and press the Finish button

    Creating 2 Other Projects:
    1. Repeat steps 1 and 2 from above
    2. Uncheck the "Create activity" box and the "Create custom launcher icon" box

    Adding The TestApp Library:
    Now that we have all 3 projects created, we need to add the TestApp Library Project to the TestAdApp and TestPaidApp projects. To do this, right-click on the TestAdApp/TestPaidApp project in the Package Explorer and go down to Properties. Go to the Android section and in the Library section, press the Add... button. Select TestLibrary from the list and press OK. Press Apply, and OK.

    Preparing MainActivity:
    The MainActivity.java file in the TestApp library should currently look like this:
    package com.example.testlibrary;
     
    import android.app.Activity;
    import android.app.Fragment;
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.ViewGroup;
     
    public class MainActivity extends Activity {
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            if (savedInstanceState == null) {
                getFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
            }
        }
     
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.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();
            if (id == R.id.action_settings) {
                return true;
            }
            return super.onOptionsItemSelected(item);
        }
     
        /**
         * A placeholder fragment containing a simple view.
         */
        public static class PlaceholderFragment extends Fragment {
     
            public PlaceholderFragment() {
            }
     
            @Override
            public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                View rootView = inflater.inflate(R.layout.fragment_main, container, false);
                return rootView;
            }
        }
    }
    We need to do a quick modification to include the ability to support both versions of our app. We will create a new method called setAdvertisements() and call that method in our onCreate() method:
    ...
        public void setAdvertisements() {
        }
     
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            setAdvertisements();
            if (savedInstanceState == null) {
                getFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
            }
        }
    ...

    Modifying The TestPaidApp Project:
    The paid app is the easy one to modify. All you have to do for this one is add your activities to the manifest. The MainActivity is inherited from the TestApp library and, since the setAdvertisements() method is empty, we don't actually have to modify anything. So, in the AndroidManifest.xml of the TestPaidApp project, we simply need to add our MainActivity:
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.testpaidapp"
        android:versionCode="1"
        android:versionName="1.0" >
     
        <uses-sdk
            android:minSdkVersion="16"
            android:targetSdkVersion="19" />
     
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
     
            <activity
                android:name="com.example.testlibrary.MainActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    </manifest>

    Modifying the TestAdApp Project:
    This is the project we need to heavily modify. First, we need to create an activity to override each of our other activites from the TestApp library.
    Now we need to include the Google Play Service library in our TestAdApp project. Follow the steps provided in this tutorial to set that up: https://developer.android.com/google...ces/setup.html
    Assuming you want all the AdViews to work the same, we can create a new class MyAdView in the TestAdApp project:
    package com.example.test;
     
    import android.app.Activity;
    import android.widget.FrameLayout;
     
    import com.google.android.gms.ads.AdRequest;
    import com.google.android.gms.ads.AdSize;
    import com.google.android.gms.ads.AdView;
     
    public class MyAdView {
     
        /** The view to show the ad. */
        private AdView adView;
     
        /* Your ad unit id. Replace with your actual ad unit id. */
        private static final String AD_UNIT_ID = "INSERT_YOUR_AD_UNIT_ID_HERE";
     
        public MyAdView(Activity context, int viewId) {
            this.adView = new AdView(context);
            this.adView.setAdSize(AdSize.BANNER);
            this.adView.setAdUnitId(AD_UNIT_ID);
     
            // Add the AdView to the view hierarchy. The view will have no size
            // until the ad is loaded.
            FrameLayout layout = (FrameLayout) context.findViewById(viewId);
            layout.addView(this.adView);
     
            // Create an ad request. Check logcat output for the hashed device ID to
            // get test ads on a physical device.
            AdRequest adRequest = new AdRequest.Builder().addTestDevice(AdRequest.DEVICE_ID_EMULATOR).addTestDevice("INSERT_YOUR_HASHED_DEVICE_ID_HERE").build();
     
            // Start loading the ad in the background.
            this.adView.loadAd(adRequest);
        }
     
        public AdView getAdView() {
            return this.adView;
        }
    }
    NOTE: You need an Ad Unit Id and the Hashed Id of your test device before you can successfully run advertisements. Also, remember to set the AdRequest to use the real device when you are ready to deploy.
    Then, we create a class which extends MainActivity. In this class, we will provide code for our setAdvertisements() methods, and we will handle the way the ad responds to activity state changes. We will create our AdView with the help of our MyAdView class. We will call our new class: MainActivityOverride
    package com.example.test;
     
    import com.example.testlibrary.MainActivity;
    import com.example.testlibrary.R;
    import com.google.android.gms.ads.AdView;
     
    public class MainActivityOverride extends MainActivity {
     
        private AdView adView;
     
        @Override
        public void setAdvertisements() {
            MyAdView myAdView = new MyAdView(this, R.id.container);
            this.adView = myAdView.getAdView();
        }
     
        @Override
        public void onResume() {
            super.onResume();
            if (this.adView != null) {
                this.adView.resume();
            }
        }
     
        @Override
        public void onPause() {
            if (this.adView != null) {
                this.adView.pause();
            }
            super.onPause();
        }
     
        /** Called before the activity is destroyed. */
        @Override
        public void onDestroy() {
            // Destroy the AdView.
            if (this.adView != null) {
                this.adView.destroy();
            }
            super.onDestroy();
        }
    }
    This pattern will need to be repeated for every activity you wish to include the banner ad on.
    The last thing we need to do is modify the manifest for our TestAdApp project. We will add the Activities the same way we did on the free version. However, we also need to add user-permissions to the app, as well as AdActivity configurations and Google Play Service metadata, in order for our advertisements to work. The updated AndroidManifest will look like this:
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.testadapp"
        android:versionCode="1"
        android:versionName="1.0" >
     
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
        <uses-permission android:name="android.permission.INTERNET" />
     
        <uses-sdk
            android:minSdkVersion="16"
            android:targetSdkVersion="21" />
     
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:name="com.example.test.MainActivityOverride"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity android:name="com.google.android.gms.ads.AdActivity"
    			android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"/>
    		<meta-data android:name="com.google.android.gms.version"
            	android:value="@integer/google_play_services_version" />
        </application>
    </manifest>

    Conclusion:
    You should now be ready to deploy and test your Ad-Free and Ad-Supported app versions.
    So, what advantage does this provide? Well, from a maintenance standpoint, you now have significantly less work on your hands. You will still need to remember to update the AndroidManifests when you create a new Activity, and you will need to remember to create an override for that new activity in the Ad-Supported version, but you are not rewriting the entire user interface for each version. You can ensure the user interfaces between your two app versions are consistent, with the only difference being one having a banner ad, and the other not. When modifying existing activities, you simply need to modify your app's library project and you will be ready to deploy both versions at the same time without any additional code changes. You have also ensured the Paid version does not have any unnecessary dependencies (such as the Google Play Service) or extra code, which only the Ad-Supported version needs.


    NOTE: This tutorial is still being revised to ensure proper accuracy and details. Please tell me if there is something I left out or if something is unclear.
    NOTE TO NEW PEOPLE LOOKING FOR HELP ON FORUM:

    When asking for help, please follow these guidelines to receive better and more prompt help:
    1. Put your code in Java Tags. To do this, put [highlight=java] before your code and [/highlight] after your code.
    2. Give full details of errors and provide us with as much information about the situation as possible.
    3. Give us an example of what the output should look like when done correctly.

    Join the Airline Management Simulation Game to manage your own airline against other users in a virtual recreation of the United States Airline Industry. For more details, visit: http://airlinegame.orgfree.com/

  2. The Following User Says Thank You to aussiemcgr For This Useful Post:

    ChristopherLowe (August 8th, 2014)


Similar Threads

  1. Best way to implement Ad-Supported and Paid app versions
    By aussiemcgr in forum Android Development
    Replies: 4
    Last Post: August 19th, 2014, 09:16 AM
  2. Creating an android app.
    By absineo in forum Android Development
    Replies: 3
    Last Post: May 13th, 2014, 05:02 PM
  3. QA for Android app
    By deependeroracle in forum Android Development
    Replies: 1
    Last Post: February 28th, 2014, 10:23 AM
  4. Hello World Android App
    By TP-Oreilly in forum Android Development
    Replies: 6
    Last Post: January 22nd, 2012, 08:01 PM