2

I've submitted an app to the Nook developers portal. It runs fine on my rooted nook color and on all the different emulators plus thousands of devices on the play store. The problem is that when I submit it, it fails to launch on any of their devices. Below is my manifest and my launch activity which it says it is Caused by: java.lang.ClassNotFoundException: com.bfreq.dice.SplashScreen in loader dalvik.system.PathClassLoader[/data/app/com.bfreq.dice-1.apk]

Is it not finding my main class or is it not finding the class which the SplashScreen loads?

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.bfreq.dice"
    android:installLocation="auto"
    android:versionCode="11"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="7"
        android:targetSdkVersion="11" />

    <supports-screens
        android:anyDensity="true"
        android:largeScreens="true"
        android:normalScreens="true"
        android:resizeable="true"
        android:smallScreens="true"
        android:xlargeScreens="true" />

    <meta-data
        android:name="ADMOB_ALLOW_LOCATION_FOR_ADS"
        android:value="true" />

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:icon="@drawable/icon"
        android:label="@string/app_name" >
        <activity
            android:name=".SplashScreen"
            android:label="@string/app_name"
            android:theme="@style/Theme.Sherlock" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".ViewPagerMain"
            android:label="@string/app_name"
            android:theme="@style/Theme.Sherlock"
            android:windowSoftInputMode="stateHidden" >
            <intent-filter>
                <action android:name="com.bfreq.dice.VPM" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
        <activity
            android:name=".CustomDiceHandler"
            android:label="@string/app_name"
            android:windowSoftInputMode="stateHidden|adjustPan" >
            <intent-filter>
                <action android:name="com.bfreq.dice.CDH" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
        <activity
            android:name=".AdProvider"
            android:label="@string/app_name"
            android:theme="@android:style/Theme.Wallpaper"
            android:windowSoftInputMode="stateHidden|adjustPan" >
            <intent-filter>
                <action android:name="com.bfreq.dice.ADP" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.google.ads.AdActivity"
            android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" >
        </activity>
    </application>

</manifest>

Here is my SplashScreen

package com.bfreq.dice;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockActivity;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnCancelListener;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.view.WindowManager;

public class SplashScreen extends SherlockActivity {

    AdProvider adTime = new AdProvider();
    DicePreferences prefs = new DicePreferences();
    static int ori = 0;
    static int time = 1000;
    static boolean firstLoad = true;

    Thread splashThread = new Thread() {
        @Override
        public void run() {
            try {
                int waited = 0;
                while (waited < time) {
                    sleep(100);
                    waited += 100;
                }
                Log.d("Hi", "I'm your thread, you should only see me once");
            } catch (InterruptedException e) {
                // do nothing
            } finally {
                Intent intent = new Intent("com.bfreq.dice.VPM");
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(intent);
                Log.d("Finished", "I just launch your intent, yay!");
                finish();
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        ActionBar actionbar = getSupportActionBar();
        actionbar.setTitle("D&D Dice");
        actionbar.setSubtitle("by b.freq");
        actionbar.hide();
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);

        prefs.loadArrayLists(this);
        prefs.loadStrings(this);
        prefs.loadSettings(this);
        prefs.loadDemo(this);

        if (adTime.getCurrentTime() > ViewPagerMain.endDemo
                && VersionCheck.demo) {
            VersionCheck.demo = false;
            ViewPagerMain.startDemo = 0;
            ViewPagerMain.endDemo = 0;
            prefs.saveDemo(this);
        }
        if (DialogFonts.sizeMain < 10 || DialogFonts.sizeDL < 10) {
            DialogFonts.sizeMain = 20;
            DialogFonts.sizeDL = 15;
            prefs.saveSettings(this);
        }

        // This is for manually changing orientation
        if (firstLoad) {
            prefs.loadOrientation(this);
            ViewPagerMain.ori = ori;
        }
        switch (ViewPagerMain.ori) {
        case 0:
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
            break;
        case 1:
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            break;
        case 2:
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            break;
        }

        setContentView(R.layout.splash);

        // Dumping assets into their sdcard
        try {
            copyStream("CustomSheet - BlankSheet.csv", this);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // This stops hardware keyboard orientation change
        if (((getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) < 3)
                & (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)) {
            // setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            AlertDialog alertDialog = new AlertDialog.Builder(this).create();
            alertDialog.setTitle("Orientation not Supported on your device!!!");
            alertDialog.setMessage("Close your KEYBOARD!!!");
            alertDialog.show();
            alertDialog.setOnCancelListener(new OnCancelListener() {
                @Override
                public void onCancel(DialogInterface dialog) {
                    finish();
                }
            });
        } else {
            splashThread.start();
        }

    }

And Finally here is the error log which they sent me.

Files: Rejected: NOOK Color, NOOK Tablet, NOOK HD, NOOK HD+
Your app has failed to launch or crashed. Please see the log that is
attached for more information.
1. Install and boot the app.
Result: The app fails to boot and displays the message " Unfortunately,
D&D Dice by b.freq has stopped."

10-10 12:57:50.670 I/ActivityManager(  958): Starting activity: Intent {
act=android.intent.action.MAIN
dat=content://applications/applications/com.bfreq.dice/com.bfreq.dice.SplashScreen
flg=0x14000000
cmp=com.android.providers.applications/.ApplicationLauncher (has extras)
}

10-10 12:57:50.720 I/ApplicationLauncher( 3546): Launching
ComponentInfo{com.bfreq.dice/com.bfreq.dice.SplashScreen}

10-10 12:57:50.732 I/ActivityManager(  958): Starting activity: Intent {
act=android.intent.action.MAIN flg=0x10200000
cmp=com.bfreq.dice/.SplashScreen }

10-10 12:57:50.763 I/SurfaceFlinger(  958):


10-10 12:57:50.763 I/SurfaceFlinger(  958):
SurfaceFlinger::createSurface() : layer->mIdentity=244, LayerName=
Starting com.bfreq.dice

10-10 12:57:50.763 I/SurfaceFlinger(  958):
SurfaceFlinger::createSurface() : layer->clientIndex=1,
surfaceHandle->mToken=0x1

10-10 12:57:50.826 I/ActivityManager(  958): Start proc com.bfreq.dice
for activity com.bfreq.dice/.SplashScreen: pid=5006 uid=10051
gids={1015, 3003}

10-10 12:57:51.092 D/AndroidRuntime( 5006): Shutting down VM

10-10 12:57:51.092 W/dalvikvm( 5006): threadid=1: thread exiting with
uncaught exception (group=0x4001d888)

10-10 12:57:51.105 E/AndroidRuntime( 5006): FATAL EXCEPTION: main

10-10 12:57:51.105 E/AndroidRuntime( 5006): java.lang.RuntimeException:
Unable to instantiate activity
ComponentInfo{com.bfreq.dice/com.bfreq.dice.SplashScreen}:
java.lang.ClassNotFoundException: com.bfreq.dice.SplashScreen in loader
dalvik.system.PathClassLoader[/data/app/com.bfreq.dice-1.apk]

It continues on for an crazy long time...

MinceMan
  • 7,483
  • 3
  • 38
  • 40
  • Please read [Android Splash Screens Done Right](http://blog.iangclifton.com/2011/01/01/android-splash-screens-done-right/) by Ian G. Clifton. – shkschneider Oct 19 '12 at 15:12

1 Answers1

2

I wouldn't call sleep in my splash screen or any other activity, that piece of code smells. Try changing that. Why not use Handler.postDelayed() Also you might get an ANR if you use sleep for a considerable amount of time.

It's simple, just do the following.

Runnable splashRunnable = new Runnable() {

    @Override
    public void run() {
        Intent intent = new Intent("com.bfreq.dice.VPM");
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(intent);
        finish();
    }
}

And in your onCreate() method:

new Handler().postDelayed(splashRunnable, SPLASH_DELAY);

Now, you are done.

Also remember, try catch blocks shouldn't be used to handle program logic, it should only be used to recover from problems. There could be exceptions sometimes, but this situation is not appropriate.

Ragunath Jawahar
  • 19,513
  • 22
  • 110
  • 155
  • Also are you running ICS / JellyBean on your Nook? – Ragunath Jawahar Oct 19 '12 at 03:31
  • I think the post delay is a good idea but am not really convinced that that is what's causing this. The nook color is running stock rooted so I have to put this in as a system apk which is not how they're installing it. I have tried the nook hd (ics) emulator and that works fine. – MinceMan Oct 19 '12 at 13:42
  • There are several things Google has done to make Android apps responsive. One such example is attempting to perform a network operations on older Android version blocks the UI but JellyBean crashes. So calling sleep on the UI thread could be a performance violation as well. So may be you should give this a try. Also let me try the Thread.sleep() on my Galaxy Nexus. – Ragunath Jawahar Oct 19 '12 at 14:09
  • Ok I'll try the postDelayed(). I've never used it before so could you throw up some simple code? – MinceMan Oct 19 '12 at 14:53
  • Cool, put that in and it works great. I also changed how I'm building my intent as it's giving me that class not found exception. Switched it to: Intent intent = new Intent(getApplicationContext(), ViewPagerMain.class); I'm going to try to submit this as today is the last submition day to guarantee getting on in time for the Nook HD. – MinceMan Oct 19 '12 at 22:50
  • 1
    So with the post delay and not using Intent filters it pass testing! So I won't use wait on threads if I can help it. Thanks for your help! – MinceMan Oct 23 '12 at 17:28