Last few days I played with AndEngine, an open source, free, games framework for Android. I'm not sure yet if AndEngine will save time building new games.
Anyhow, one weird part in AndEngine is the way you load all the resources into a single canvas. You have to define the location of each resource on the canvas, and if you change the resource size you have to recalculate everything.
Here is a simple extension to BitmapTextureAtlas that calculate everything automatically and saves you the trouble of positioning the resources on the canvas.
And this is how to use it (in the onLoadResources funcation):
Monday, October 24, 2011
Tuesday, October 18, 2011
Free resources for applications
This post is a work in progress.
Here are few places I've found for useful for free resources. You should verify if the specific resource license fit your needs.
Free fonts:
*. http://www.fontsquirrel.com/ (verify the copy rights per font, most are not really free)
*. http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL (read the OFL license first)
Free clip arts:
*. http://www.openclipart.org/.
*. Huge list of sites that contain free images.
Free music/sound affects:
*. http://www.freesound.org - Creative common license.
*. There are many sites that looks OK, just search for 'free sound effects'.
A bit off-topic - royalty free resources (not free):
*. Music loops
*. Tons of resources: The Marketing Guide for Game Developer
Here are few places I've found for useful for free resources. You should verify if the specific resource license fit your needs.
Free fonts:
*. http://www.fontsquirrel.com/ (verify the copy rights per font, most are not really free)
*. http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL (read the OFL license first)
Free clip arts:
*. http://www.openclipart.org/.
*. Huge list of sites that contain free images.
Free music/sound affects:
*. http://www.freesound.org - Creative common license.
*. There are many sites that looks OK, just search for 'free sound effects'.
A bit off-topic - royalty free resources (not free):
*. Music loops
*. Tons of resources: The Marketing Guide for Game Developer
Tuesday, October 11, 2011
Monetizing Android applications
In a recent talk I've heard by Itay Rokni of StartApp.com he listed the various monetizing options Android developer has (to date):
Few notes if you're using In app ads:
- In app ads - Ads inside the application: banners, full page, leads generators etc. See for example AdMob.
- Paid apps - The user pay to get the application. Not free options.
- Freemium - Basic application is free, the user can buy the full application or in-app buy more features.
- Notification bar ads - Ads that appear not inside the application, but in the notification bar. For example see airpush.com.
- Search icon - Create a search icon after app installation. The provider pay per installation or revenue share. For example see StartApp.com
Few notes if you're using In app ads:
- Trust no one - AdMob is the industry benchmark and every says 'we're better than AdMob'. I found this statement to be almost always wrong.
- Use mediation layer - Use mediation layer such as AdWhirl to control which ad networks you're using. Ad networks go up and down, it's better to control the follow of ads dynamically and not depend on updating the APK in the market.
Labels:
Android
Tuesday, September 27, 2011
Bulk image resizing/changing format
Sometimes there's a need to resize images or just changes their formats. Mostly if the original is on high resolution or improper format for mobile applications. While there are many tools to do this, the best I've found is a plug-in for Paint.NET called Paint.NET Bulk Image Processor. It's free, open source and super easy to use.
Wednesday, August 10, 2011
innerActive & AdWhirl, take 2
Few days ago I've published a post how to make an AdWhirl adapter for innerActive. Just after publishing the post I've noticed innerActive released a major version for their Android SDK (3.0.3).
Here is the new adapter:
Here is the new adapter:
import android.app.Activity;
import android.util.Log;
import android.view.View;
import com.adwhirl.AdWhirlLayout;
import com.adwhirl.AdWhirlLayout.AdWhirlInterface;
import com.inneractive.api.ads.InneractiveAdEventsListener;
import com.inneractive.api.ads.InneractiveAdView;
import com.inneractive.api.ads.InneractiveAdComponent;
public class InnerActiveCustomEvents implements AdWhirlInterface {
private static final String INNERACTIVE_PUBLISHER_ID = "TBD";
private AdWhirlLayout mAdWhirlLayout;
private Activity mActivity;
public AdWhirlMultipleCustomEvents(AdWhirlLayout mAdWhirlLayout, Activity mActivity) {
super();
this.mAdWhirlLayout = mAdWhirlLayout;
this.mActivity = mActivity;
}
public void adWhirlGeneric() {
}
public void inneractiveBanner() {
// BUGBUG - This fixes the Android OS bug with 'getCacheTotalSize' which causes
// NullPointerException prior to Android 2.3, see also:
// http://code.google.com/p/android/issues/detail?id=10789
android.webkit.WebViewDatabase webViewDB = android.webkit.WebViewDatabase.getInstance(mActivity);
if (webViewDB == null) {
mAdWhirlLayout.rollover();
return;
}
InneractiveAdView banner = InneractiveAdComponent.getAdView(mAdWhirlLayout.getContext(), INNERACTIVE_PUBLISHER_ID, InneractiveAdComponent.BANNER_AD_TYPE, 0);
banner.setListener(new InneractiveAdEventsListener() {
@Override
public void onReceiveAd(InneractiveAdView adView) {
adView.setVisibility(View.VISIBLE);
Log.v("InnerActive Banner Listener", "Received Ad.");
mAdWhirlLayout.handler.post(new AdWhirlLayout.ViewAdRunnable(mAdWhirlLayout, adView));
mAdWhirlLayout.adWhirlManager.resetRollover();
mAdWhirlLayout.rotateThreadedDelayed();
}
@Override
public void onFailedToReceiveAd(InneractiveAdView adView) {
Log.v("InnerActive Banner Listener", "Failed To Receive Ad.");
mAdWhirlLayout.rollover();
}
@Override
public void onClickAd(InneractiveAdView adView) {
}
});
}
}
Labels:
Android
Thursday, August 4, 2011
Using innerActive ads on Android (with AdWhirl)
UPDATE- This post is obsolete, please check this update post.
I've decided to try using multiple ad agencies, and one of them was innerActive. I had 2 problems with innerActive: (1) They don't supply an AdWhirl adapter, (2) There's seem to be a bug in their SDK as of version 2.0625
Problem A: The bug
The function onWindowFocusChanged which runs on the UI thread calls the function setRefreshInterval which has the keyword synchronized which means it waits for a lock. The lock is taken by the ad request thread. If the onWindowsFocusChanged will be called during an ad request there will be an ANR exception due to a delay on the UI thread.
Solution:
I wrote a wrapper that seems to fix this issue.
Problem B: No AdWhirl adapter
Solution:
I wrote a custom AdWhirl adapter for innerActive.
I'm not going to write a step-by-step guide, but here is the key notes:
Notes -
I've decided to try using multiple ad agencies, and one of them was innerActive. I had 2 problems with innerActive: (1) They don't supply an AdWhirl adapter, (2) There's seem to be a bug in their SDK as of version 2.0625
Problem A: The bug
The function onWindowFocusChanged which runs on the UI thread calls the function setRefreshInterval which has the keyword synchronized which means it waits for a lock. The lock is taken by the ad request thread. If the onWindowsFocusChanged will be called during an ad request there will be an ANR exception due to a delay on the UI thread.
Solution:
I wrote a wrapper that seems to fix this issue.
import java.util.concurrent.locks.ReentrantLock;
import android.content.Context;
import android.util.AttributeSet;
import com.innerActive.ads.InnerActiveAdView;
public class InnerActiveAdViewFixed extends InnerActiveAdView {
private ReentrantLock mLock = new ReentrantLock();
public InnerActiveAdViewFixed(Context context) {
super(context);
}
public InnerActiveAdViewFixed(Context context, AttributeSet attrs) {
super(context, attrs);
}
public InnerActiveAdViewFixed(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
// Patch
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
if (mLock.tryLock() == true) {
try {
super.onWindowFocusChanged(hasWindowFocus);
} finally {
mLock.unlock();
}
}
}
@Override
public byte start() {
mLock.lock();
try {
return super.start();
} finally {
mLock.unlock();
}
}
}
Problem B: No AdWhirl adapter
Solution:
I wrote a custom AdWhirl adapter for innerActive.
import android.util.Log;
import android.view.View;
import com.adwhirl.AdWhirlLayout;
import com.adwhirl.AdWhirlLayout.AdWhirlInterface;
import com.innerActive.ads.InnerActiveAdView;
public class InnerActiveCustomEvents implements AdWhirlInterface{
private AdWhirlLayout mAdWhirlLayout;
public InnerActiveCustomEvents(AdWhirlLayout adWhirlLayout) {
super();
this.mAdWhirlLayout = adWhirlLayout;
}
@Override
public void adWhirlGeneric() {
}
public void inneractiveBanner() {
final InnerActiveAdViewFixed banner = new InnerActiveAdViewFixed(mAdWhirlLayout.getContext());
banner.setVisibility(View.VISIBLE);
banner.setRefreshInterval(0);
banner.setScrollContainer(true);
banner.setBgColor(0xFF000000);
banner.setTxtColor(0xFFFFFFFF);
banner.setListener(new InnerActiveAdView.AdEventsListener() {
@Override
public void onReceiveAd(InnerActiveAdView arg0) {
banner.setVisibility(View.VISIBLE);
Log.v("InnerActive Banner Listener", "Received Ad.");
mAdWhirlLayout.handler.post(new AdWhirlLayout.ViewAdRunnable(mAdWhirlLayout, banner));
mAdWhirlLayout.adWhirlManager.resetRollover();
mAdWhirlLayout.rotateThreadedDelayed();
}
@Override
public void onFailedToReceiveAd(InnerActiveAdView arg0) {
Log.v("InnerActive Banner Listener", "Failed To Receive Ad.");
mAdWhirlLayout.rollover();
}
});
}
}
I'm not going to write a step-by-step guide, but here is the key notes:
- Integrate innerActive ads & make sure everything works.
- Remove the ad view from the layout & the appropriate code the the ad view.
- Integrate AdWhirl:
3.1. Create an application in AdWhirl web site & get SDK Key
3.2. Add AdWhirl JAR
3.3. Add the AdWhirl SDK Key to the AndroidManifest.xml
3.4. Add the com.adwhirl.AdWhirlLayout to the application layout - Add the following code (in the onCreate functions)
AdWhirlLayout adWhirlLayout = (AdWhirlLayout)findViewById(R.id.adwhirl_layout);
adWhirlLayout.setAdWhirlInterface(new InnerActiveCustomEvents(adWhirlLayout)); - Add innerActive to AdWhirl as custom event - name: innerActive, function name: inneractiveBanner
Notes -
- If you're using multiple custom events, they should all be in the same function, so copy only the inneractiveBanner function.
- If you're using ProGaurd make sure you read my previous post & also add the custom events adapter & innerActive ad views to the ProGuard exceptions list.
Labels:
Android
Friday, July 15, 2011
ProGuard & AdWhirl
Compilation of an application with AdWhirl & ProGuard throws many warning, for all those AdWhirl adapter libraries not compiled with the application. I found multiple solutions online, some saying just ignore all the warning ProGuard throws:
-ignorewarnings
Don't use it - there's a better solution, ignoring only the problematic parts:
-dontwarn com.adwhirl.adapters.*
Here's the best solution for Proguard & AdWhirl as far as I know:
-dontwarn com.adwhirl.adapters.*
-keep class com.adwhirl.** { *;}
-keep public class com.adwhirl.adapters.AdMobAdapter {*;}
-keep public class com.adwhirl.adapters.ZestAdzAdapter {*;}
-keep public class com.adwhirl.adapters.MillennialAdapter {*;}
-keep public class com.admob.android.ads.** {*;}
-keep public class com.millennialmedia.android.** {*;}
-keep public class com.zestadz.android.** {*;}
-keep public class * extends Android.view.View {
public(android.content.Context);
public(android.content.Context, android.util.AttributeSet);
public(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}
-keepclassmembers class *{
public void *(android.view.View);
}
-ignorewarnings
Don't use it - there's a better solution, ignoring only the problematic parts:
-dontwarn com.adwhirl.adapters.*
Here's the best solution for Proguard & AdWhirl as far as I know:
-dontwarn com.adwhirl.adapters.*
-keep class com.adwhirl.** { *;}
-keep public class com.adwhirl.adapters.AdMobAdapter {*;}
-keep public class com.adwhirl.adapters.ZestAdzAdapter {*;}
-keep public class com.adwhirl.adapters.MillennialAdapter {*;}
-keep public class com.admob.android.ads.** {*;}
-keep public class com.millennialmedia.android.** {*;}
-keep public class com.zestadz.android.** {*;}
-keep public class * extends Android.view.View {
public
public
public
public void set*(...);
}
-keepclassmembers class *{
public void *(android.view.View);
}
Labels:
Android
Subscribe to:
Comments (Atom)