AuthorJohannes Borchardt

The new madvertise Android-SDK

Three days ago, madvertise, one of my favourite ad networks, updated its Android SDK in a major update to 2.0. So what changed and what’s new? Here is an overview over the major changes.

First of all, get the new SDK here.

How to make it work again: Renamed classes

When updating the new SDK, there are some minor changes a developer has to consider.

In order to make the naming of the SDK for iOS and Android equal, the names of the classes have been changed. Every class that started with ‘Mad‘ before now starts with ‘Madvertise’. So the MadViewCallbackListener is now called MadvertiseViewCallbackListener and the MadView is now called MadvertiseView. Accordingly, the method to set the MadvertiseViewCallbackListener is now called setMadvertiseViewCallbackListener(), not setMadViewCallbackListener().

The MadvertiseViewCallbackListener now has two more callback methods:

public void onError(Exception exception)

which will be called when an exception in the SDK occurs and

public void onIllegalHttpStatusCode(int statusCode, String message)

which will be called when the madvertise-Server returns something different than a HTTP status code 200. The code you will probably see the most is a 204, which means that the device requesting an ad is not yet known to the madvertise-Server.

Also, the banner-type ‘iab’ has been renamed to ‘medium_rectangle’. However, at the moment ‘iab’ still works.
When you included all these changes, everything should work fine again.

New functionality

The update of the SDK adressed some bugs many of you experienced. Here is an excerpt:

  • Requests are now interrupted when a MadvertiseView is destroyed.
  • No reloading of ads when a phone is turned, keyboard is being opened, and so on, anymore.
  • Banners are scaled correctly now.
  • Before, when the request interval was set to <60, it was adjusted to 30 automatically.
  • The width of a MadvertiseView was sometimes not calculated correctly

There are also some improvements where you have to do nothing to activate them:

  • Animated banners: Ads provided as animated GIFs are now played when the device is capable of doing so.
  • Banners are shown automatically now, so you don’t need a MadvertiseViewCallbackListener to make your ads visible anymore.
  • Ads now don’t acquire space in the layout before they are shown.
  • Multiple ads: You can now display more than one ad on a screen, for example one fixed on top and one in a list. However, the total number of ads on a screen should not exceed four.

And there are some new features you should think of when integrating the new SDK:

  • New banner formats – you can now display the following banner types:
    • mma (320×53)
    • medium_rectangle (320×200)
    • leaderboard (728×90)
    • fullcreen (768×768)
    • portrait (766×66)
    • landscape (1024×66)
  • Multiple banner formats – you can now request multiple banner formats in your XML-declaration of a MadvertiseView like this:
           <de.madvertise.android.sdk.MadvertiseView
             android:id="@+id/madad"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             mad:isTestMode="false"
             mad:backgroundColor2="#000000"
             mad:textColor="#FFFFFF"
             mad:bannerType="mma,portrait,landscape,leaderboard"
             mad:deliverOnlyText="false"
             />

The list is sorted by priority. So in the above example, when there is no mma-banner available, a portrait-banner will be shown, when there is no portrait-banner, a landscape-banner will be shown, and so on.

  • Animations: Ads can now be animated when they are received. To add an animation, add <attr name="animation" format="string" /> to your attrs.xml file. Now you can set animations in your XML-layout using mad:animation. You can choose between fade (default), left_to_right and top_down.
  • New request parameters: You can set the gender and age of your users by calling MadvertiseView.setGender() or MadvertiseView.setAge(). As these methods are static, it is recommended to call them before your layout is inflated.

 Conclusion

The new madvertise SDK comes with some nice new features and bug fixes. The new formats are suitable for tablets and phones with large screens like the Galaxy Nexus. I’m curious whether the animation banners and animation of new banners will lead to more clicks.

 

Please feel free to leave your thoughts and questions on the new update in the comments below.

App Store Optimization (ASO) (3/5): Graphics & Videos

Finally, the next part on App Store Optimization (ASO) arrived.

If you are new to this series, I recommend to start from the first article on App Store Optimization. If you don’t want to read that much, this article can still give you valuable information on its own.

Parts of this series on App Store Optimization are:
1. Keywords
2. Description

3. Icons
4. Graphics
5. Videos
6. Ratings
7. Installs
8. Users

While the last article covered Icons, we will stay in the design area for this one. This time, graphics and videos will be covered.

4. Graphics

First, when I say graphics I mean every image except the icon provided via the Android Market Developer Console. This includes the screenshots and the promotional graphic with which I will start.

Promotional Graphics
Promotional Graphics are the big graphics shown on top of your app’s screenshots and description in the Android Market. If you want to get featured, this graphic is required. So although it’s optinal in the developer console, you should always upload your promotional image. For an overview on how this graphic should look like, I recommend reading this post from the official Android Developers Blog.

The promotional graphic is 1024 * 500 pixels in size, so you have a lot of space you can fill. Still, your graphic should not be packed with huge text since it will be scaled down to different sizes. Let me demonstrate this by an example used on the Android Developers Blogpost mentioned above:

Big promotional graphic

Big promotional graphic

This is the size a promo graphic has on the Android Market website.

Scaled down promotional graphic

Scaled down promotional graphic

This is the same image scaled down to the size it would have on a small phone or in one of the smaller feature places in the Android Market app. When taking a look at the image, I think they could have used a different font type since the ‘U’ is not completely visible anymore when downscaled.

This scaling is the reason why your promotional image should be used to place a high resolution graphic that fits to your app. A big writing of your slogan or app’s name is also appropriate.
It is recommended to use colors other than black or white as a background to differenciate between your image and the Android Market’s design. Personally, I like those graphics that fit into the Markets own color scheme and float over to the description and screenshots, so I think this should be treated in the way you like best. Nonetheless, your background and foreground colors should have a good contrast so that your graphic can be captured by the viewer easily.
What you never should do is reuse content that is provided by the Android Market anyway. So don’t use screenshots, icons or your app’s description in your promotional graphic.

Screenshots
Screenshots should represent your app. When your app is not beautiful, then your screenshots aren’t. This leads to the biggest problem most developers have: They are experts in programming, but not in design or usability and are not able to write beautiful apps. When this is the case, there are two ways you can go, ideally you combine them.

The first way is to hire a designer, tell him what you need and implement that design. The second way is to implement a design on your own and do some Bambi tests. Bambi tests are done in this way: You look for someone of your potential target group that never tried your app, the Bambi. You give them a device with which they can try out your app without any advice. Don’t say a word, just let them try. Be careful about the way they use your app, about what’s intuitive to them and what’s not. Improve your app and look for another Bambi to test again. Ideally, you have a team consisting out of developers and designers and some hand full of potential Bambis. Remember: Once a Bambi-User tested your app, it will never be a Bambi-User for this app again.

The term Bambi test goes back to Mohammed El Batya, creator of the Pendel Panda timetable.

There are a lot of things you can study when it comes to app design and usability, but in the end your app has to be as useful and intuitive as possible to your users. Your screenshots should look exactly like your app does and represent the functionality your app provides. Whether you show ads that are used in your app on your screenshots depends in most cases on your taste. In some app stores, like the Amazon App Store, you won’t pass the approval procedure when you don’t.

To give you an overview on the improvements a designer can make to your app, here are the screenshots of the AL Voice Recorder before and after it was totaly redesigned:

Old design of the file browser of the AL Voice Recorder

Old design of the file browser of the AL Voice Recorder

Old design of the record screen of the AL Voice Recorder

Old design of the record screen of the AL Voice Recorder

New design of the file browser of the AL Voice Recorder

New design of the file browser of the AL Voice Recorder

New design of the record screen of the AL Voice Recorder

New design of the record screen of the AL Voice Recorder

Which one would you prefer to download?

5. Videos

While screenshots are a static representation of your app, you can show the flow, the effects and the ‘WOW!’ in your videos.
Videos should have a short and clear message that describes what your app is all about and why a user should download it. They should be short (not more then 1.5 to 2 minutes) and entertaining. Long and boring videos won’t be viewed until they are finished anyway. They should have sounds and show scenes of your application the most time. They should be clearly structured with a start (e. g. a logo fading in and out), a main part (your app) and an end (e. g. an invitation to download now, an URL or else). Since many cellphone users don’t enable sound, it’s good to show what you want to tell them in your visuals, for example as a fade-in text stating ‘the most innovative arcade game you ever played’.

Personally, I watch videos especially when an app is not free, so I get to know its flow. When apps are free, I just download them and try them out on my own.
Like the promotional graphics, videos are optional. Still, they are a way for you to get some more downloads and are perfect for sharing, so there is no reason why you shouldn’t make one.

 

 

I hope you liked this one. I’d love to hear your own thaughts and experiences with graphics and videos on the Android Market in the comments.

Tutorial: How to play animated GIFs in Android – Part 3

Animated GIFs in Android is a difficult topic. It is an issue that has been discussed heavily and still, it is very difficult for developers to bring GIFs to life. There are three ways to animate GIFs on Android, each of them has its pros and cons. Each part of this series will cover one of these approaches.

Getting started

For this example, we will use an image I found on gifs.net, it’s this one:

I will store it in our project’s asset folder and name it ‘piggy.gif’. We will also use an Activity to set the views we define as content views. If you want to know everything about playing GIFs, please start at part one.

Approach 3: Using a WebView

This is the by far easyest way. As you might know, a WebView is able to do what a browser does. And since the browser of Android devices using Android 2.2 + supports the animation of GIFs (at least on most devices), we can just use that.

So, at first, we extend our own class by a WebView:

public class GifWebView extends WebView

We create a constructor that takes both a context to call the constructor of the mother-class and a path to the file. We use loadUrl() to load that file into our WebView:

   public GifWebView(Context context, String path) {
      super(context);
      loadUrl(path);
   }

Now, let’s go back to our Activity which we created in the first tutorial. Here, we create our view and pass it a context and path to our GIF-file:

   GifWebView view = new GifWebView(this, "file:///android_asset/piggy.gif");
   setContentView(view);

And now, believe it or not, we are done.

Movie, GifDecoder or WebView?

Which way you take depends on your needs. When your app is targeting users mainly using devices with Android 2.2+, the way described above is probably your way to go. If you want to support as many devices as possible and don’t care much about memory footprint, you can also use the GifDecoder-method. When you want to support many users but don’t want to recycle tons of Bitmaps, and are sure the format of your GIFs can be played using the Movie-class, then this approach is for you.

Personally, I prefer the WebView-way. Because WebKit is already implemented native, it’s memory footprint is really low, especially when compared to the GifDecoder. Operations on images like scaling can be performed simply by using HTML and the overall code is really short and pretty.

 

You can checkout the code of the three parts of this series at http://code.google.com/p/animated-gifs-in-android/.

 

Which method do you like best? As always, please feel free to leave your thoughts in the comments.

Tutorial: How to play animated GIFs in Android – Part 2

Animated GIFs in Android is a difficult topic. It is an issue that has been discussed heavily and still, it is very difficult for developers to bring GIFs to life. There are three ways to animate GIFs on Android, each of them has its pros and cons. Each part of this series will cover one of these approaches.

Getting started

For this example, we will use an image I found on gifs.net, it’s this one:

I will store it in our project’s asset folder and name it ‘piggy.gif’. We will also use an Activity to set the views we define as content views. If you want to know everything about playing GIFs, please start at part one.

Approach 2: Extracting the Bitmaps

For this approach, we will use the GifDecoder class published here on googlecode. It’s Apache licensed, so don’t worry. What this class esentially does is, it extracts the different bitmaps from the given stream so you can use it the way you want.

To get started, download this class first. Place it somewhere in your project, maybe in a util package.
Now, we create a new class which inherits from ImageView:

   public class GifDecoderView extends ImageView

We create a constructor with a Context and an InputStream, just like in the first part of this series. This time, we call a method playGif(InputStream) and pass it our InputStream:

   public GifDecoderView(Context context, InputStream stream) {
      super(context);
      playGif(stream);

We give our class five member variables: A boolean which will state whether the thread we will use to play our animation is runningor not, an instance of the GifDecoder-class you just downloaded, a Bitmap which stores the different frames of the animation, a Handler to post our updates to the UI-thread and a Runnable that will arrange that the Bitmap we just defined will be drawn using the Handler:

   private boolean mIsPlayingGif = false;

   private GifDecoder mGifDecoder;

   private Bitmap mTmpBitmap;

   final Handler mHandler = new Handler();

   final Runnable mUpdateResults = new Runnable() {
      public void run() {
         if (mTmpBitmap != null && !mTmpBitmap.isRecycled()) {
            GifDecoderView.this.setImageBitmap(mTmpBitmap);
         }
      }
   };

Let’s take a look at playGif(InputStream). First, we need to initialise mGifDecoder. After that, we let it read our stream and set mIsPlayingGif to true, so that our thread can run:

   private void playGif(InputStream stream) {
      mGifDecoder = new GifDecoder();
      mGifDecoder.read(stream);
      mIsPlayingGif = true;

Now we need to define our thread. We retreive the frame count of our GIF’s frames and the number of repetitions. When GifDecoder.getLoopCount() returns 0, this means the GIF should be played infinitely. Now for every frame, we receive the according Bitmap by calling getFrame() on the GifDecoder. We post our new Bitmap using the Handler and Runnable members we defined and send our thread to sleep until the next Bitmap needs to be drawn.

new Thread(new Runnable() {
         public void run() {
            final int n = mGifDecoder.getFrameCount();
            final int ntimes = mGifDecoder.getLoopCount();
            int repetitionCounter = 0;
            do {
              for (int i = 0; i < n; i++) {
                 mTmpBitmap = mGifDecoder.getFrame(i);
                 final int t = mGifDecoder.getDelay(i);
                 mHandler.post(mUpdateResults);
                 try {
                    Thread.sleep(t);
                 } catch (InterruptedException e) {
                    e.printStackTrace();
                 }
              }
              if(ntimes != 0) {
                 repetitionCounter ++;
              }
           } while (mIsPlayingGif && (repetitionCounter <= ntimes))
        }
     }).start();

That’s it. All we have to do now is use our GifDecoderView in an Activity, just like we did in the last part of this tutorial:

   // ...
   InputStream stream = null;
   try {
      stream = getAssets().open("piggy.gif");
   } catch (IOException e) {
      e.printStackTrace();
   }

// GifMovieView view = new GifMovieView(this, stream);
   GifDecoderView view = new GifDecoderView(this, stream);

   setContentView(view);
   // ...

 

Now, what’ the bad thing about this? It’s the memory footprint. Bitmaps on pre-Honeycomb-devices are stored in an native heap, not in the heap the Dalvik VM uses. Still, this heap counts to the maximum of memory your app can use. So when you have a lot of Bitmaps, the garbage collector might not notice that you are running out of memory because it only controls the heap of the Dalvik VM. To avoid this, make sure you call recycle() on every Bitmap you don’t need anymore. If you want to see how much space your native heap allocated, call Debug.getNativeHeapAllocatedSize().

If you want to know another, maybe better way of playing animated GIFs, stay tuned: The next part of this series will come soon.

 

You can checkout the code of the three parts of this series at http://code.google.com/p/animated-gifs-in-android/.

 

As always, please feel free to leave your thoughts in the comments.

© 2024 Droid-Blog

Theme by Anders NorenUp ↑