Go Back   Android Forums > Android Development > Application Development
Application Development Dev Lounge for the Coder Folks
Gamers - Check out our new sister sites!
Nintendo Wii U!    |    OUYA - $99 Android System!

test: Reply
 
LinkBack Thread Tools
Old October 29th, 2012, 07:00 PM   #1 (permalink)
New Member
Thread Author (OP)
 
Join Date: Oct 2012
Posts: 3
 
Device(s): HTC G2
Carrier: Not Provided

Thanks: 2
Thanked 0 Times in 0 Posts
Default First Android App and a Null Bundle Object

I've gone through the Notepad Tutorials and they are all working on my virtual device. I am now stuck in the midst of trying to write my own Android app. If I've left out any information that will help you help me, please let me know.

My setup:
Windows 7 SP 1 64-bit
Eclipse Indigo Service Release 2
Android Development Tools 16.0.1.v201112150204-238534
Android Virtual Device Platform 2.3.3, API Level 10, CPU/ABI ARM (armeabi)

The app is about as simple as they come - you enter a number, it divides it by another number and displays the result.

Here is the code involved:

AndroidManifest.xml:
Code:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.driving"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />

    <application
        android:icon="@drawable/puttputt"
        android:label="@string/app_name" >
        <activity
            android:name=".DrivingTimeEstimatorActivity"
            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=".DrivingTimeEstimator" />
    </application>

</manifest>
/res/layout/main.xml:
Code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/input_miles" />
    <EditText
        android:id="@+id/miles"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="number"
        android:hint="@string/input_miles_hint" />
    
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/time_to_go" />
    <TextView
        android:id="@+id/time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    
    <Button
        android:id="@+id/go_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/go_button" />

</LinearLayout>
/res/menu/main_menu.xml:
Code:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/go"
        android:title="@string/go" />
    <item android:id="@+id/exit"
        android:title="@string/exit" />
</menu>
/res/values/strings.xml:
Code:
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="hello">Time to estimate some drive times!</string>
    <string name="app_name">DrivingTimeEstimator</string>
    
    <string name="input_miles">Miles you\'re driving:</string>
    <string name="input_miles_hint">Enter a number between 1 and 24,000</string>
    
    <string name="time_to_go">Time it\'ll take to go the parenthesized number of miles: </string>
    <string name="go_button">Go</string>
    
    <string name="go">Go</string>
    <string name="exit">Exit</string>

</resources>
/gen/com/android/driving/R.java (figured it might come in handy, even though it's auto-generated):
Code:
/* AUTO-GENERATED FILE.  DO NOT MODIFY.
 *
 * This class was automatically generated by the
 * aapt tool from the resource data it found.  It
 * should not be modified by hand.
 */

package com.android.driving;

public final class R {
    public static final class attr {
    }
    public static final class drawable {
        public static final int ic_launcher=0x7f020000;
        public static final int puttputt=0x7f020001;
    }
    public static final class id {
        public static final int exit=0x7f060004;
        public static final int go=0x7f060003;
        public static final int go_button=0x7f060002;
        public static final int miles=0x7f060000;
        public static final int time=0x7f060001;
    }
    public static final class layout {
        public static final int main=0x7f030000;
    }
    public static final class menu {
        public static final int main_menu=0x7f050000;
    }
    public static final class string {
        public static final int app_name=0x7f040001;
        public static final int exit=0x7f040007;
        public static final int go=0x7f040006;
        public static final int go_button=0x7f040005;
        public static final int hello=0x7f040000;
        public static final int input_miles=0x7f040002;
        public static final int input_miles_hint=0x7f040003;
        public static final int time_to_go=0x7f040004;
    }
}
/src/com/android/driving/DrivingTimeEstimatorActivity:
Code:
package com.android.driving;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Button;

public class DrivingTimeEstimatorActivity extends Activity implements OnTouchListener {
    private static final int ACTIVITY_CALCULATE=0;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        Button goButton = (Button) findViewById(R.id.go_button);
        
        goButton.setOnClickListener(new View.OnClickListener() {            
            @Override
            public void onClick(View view) {
                calculate();
            }
        });
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub
        return false;
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_menu, menu);
        return true;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.go:
            calculate();
            return true;
        case R.id.exit:
            // TODO
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }
    
    private void calculate() {
        Intent i = new Intent(this, DrivingTimeEstimator.class);
        startActivityForResult(i, ACTIVITY_CALCULATE);
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        Bundle extras = intent.getExtras();
        switch (requestCode) {
        case ACTIVITY_CALCULATE:
            break;
        }
    }
}
/src/com/android/driving/DrivingTimeEstimator:
Code:
package com.android.driving;

import android.app.Activity;
import android.os.Bundle;
import android.widget.EditText;

public class DrivingTimeEstimator extends Activity {
    
    private double miles;
    private double mph;
    private final int CONVERSION_FACTOR = 60;
    
    private EditText mMiles;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        setContentView(R.layout.main); // suggested by Kostas G
        mMiles = (EditText) findViewById(R.id.miles);
        String strMiles = mMiles.getText().toString();
        miles = Double.parseDouble(strMiles);
        
        mph = 60;
        
        String time = "";
        double hours = 0;
        double minutes = 0;
        
        hours = miles/mph;
        
        if (miles%mph != 0) {
            double hoursInt = Math.floor(hours);
            double leftover = hours - hoursInt;
            minutes = leftover * CONVERSION_FACTOR;
            double minutesInt = Math.floor(minutes);
            
            time = hoursInt + " hours and " + minutesInt + " minutes";
        } else {
            time = hours + " hours";
        }
        
        time = getPrettyText(time);
    }

    private String getPrettyText(String time) {
        time = "It will take you " + time;
        time += " to go " + miles + " miles doing " + mph + " mph";
        time = time.replace(".0", "");
        return time;
    }

}
The problem:
By the time DrivingTimeEstimator's onCreate() method gets executed, the Bundle object (savedInstanceState) is null (which I'm guessing is what leads to mMiles being null, which throws a NullPointerException and kills everything). Does anyone have any ideas as to why? Thanks in advance.

whoisdagny is offline  
Last edited by whoisdagny; October 30th, 2012 at 02:33 PM. Reason: setContentView(R.layout.main); // suggested by Kostas G
Reply With Quote
Sponsors
Old October 30th, 2012, 04:59 AM   #2 (permalink)
Junior Member
 
Join Date: Aug 2012
Location: Athens, Greece
Posts: 43
 
Device(s):
Carrier: Not Provided

Thanks: 6
Thanked 7 Times in 7 Posts
Default

The savedInstanceState is null, because this is the first time you run the activity. That makes sense and isn't the root of NullPointerException.

The problem is that you haven't called setContentView in the onCreate method. You can't call findViewById before setting the view:

Code:
setContentView(R.layout.main);
Kostas G is offline  
Reply With Quote
The Following User Says Thank You to Kostas G For This Useful Post:
whoisdagny (November 2nd, 2012)
Old October 30th, 2012, 02:32 PM   #3 (permalink)
New Member
Thread Author (OP)
 
Join Date: Oct 2012
Posts: 3
 
Device(s): HTC G2
Carrier: Not Provided

Thanks: 2
Thanked 0 Times in 0 Posts
Default

Thanks, Kostas - I'd thought from the tutorials that setContentView was to be called in the onCreate method of the class that extends an Activity.

I've added the line you suggested to the main class' onCreate method (and updated the code in my original post to reflect that), and mMiles no longer comes through as null.

Its text does come through as an empty string, however, despite my having entered a number into the input field.

All the same, I appreciate your help.
whoisdagny is offline  
Reply With Quote
Old October 30th, 2012, 03:16 PM   #4 (permalink)
Junior Member
 
Join Date: Aug 2012
Location: Athens, Greece
Posts: 43
 
Device(s):
Carrier: Not Provided

Thanks: 6
Thanked 7 Times in 7 Posts
Default

This is because the onCreate method is only called once, before you enter some text in the field. You need read the string after you have written it. There is an addTextChangeListener event you can use.
Kostas G is offline  
Reply With Quote
The Following User Says Thank You to Kostas G For This Useful Post:
whoisdagny (November 2nd, 2012)
Reply


Go Back   Android Forums > Android Development > Application Development
Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



All times are GMT -5. The time now is 03:40 AM.
Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2013, vBulletin Solutions, Inc.