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
Tuesday, October 18, 2011
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
Sunday, July 10, 2011
Error conversion to Dalvik format failed with error 1
UPDATE: This issue was fixed in SDK Tools 17. If you have SDK Tools 17+ the solution here will not help you.
There is a bug in the latest Android SDK Tools (revisions 12, 13, 14, 15 & 16) which cause the following error:
Error conversion to Dalvik format failed with error 1
when you try to export your Android application & got Proguard enabled.
Google will probably fix it within few days, until then DO NOT UPDATE to Android SDK Tools revision 12. Someone already opened a bug on this issue.
Solution 1 - Restore SDK Tools v11 (ugly but it works):
If you did upgrade, the instructions how to install Android SDK Tools v11 on top can be found here. I did something similar which I think is safer & easy to undo:
1. Download Android SDK Tools v11 installer from here: http://dl.google.com/android/installer_r11-windows.exe
2. Rename the existing Android SDK\Tools folder to Tools-v12
3. Open the installer using 7zip, go to folder $_OUTDIR, and copy the folder 'Tools' the the position under Android SDK folder.
Solution 2 - Upgrade to Proguard 4.7 (needs to be reapplied after every SDK Tools upgrade):
Manually update Proguard to version 4.7. You'll have to do it again after each update of the SDK Tools.
1. Download Proguard 4.7 (zip): http://sourceforge.net/projects/proguard/files/proguard/4.7/
2. Extract the folders "bin" & "lib" from the zip on top the existing Proguard installation in the SDK Tools Proguard folders "bin" & "lib", should be around here (Win x64):
C:\Program Files (x86)\Google\Android SDK\tools\proguard
Labels:
Android
Subscribe to:
Comments (Atom)