First Experience of Android Development

Keywords: Java Android xml Attribute

This paper develops an application to learn the basic concepts of Android and its UI components.
The application developed is called GeoQuiz, which can give a lot of questions about geographic knowledge. Users click the true or false button to answer questions, and the application gives immediate feedback.

First step, please create a new project by yourself. The catalogue is as follows.

1. User Interface Design

  • Define components in an XML file (activity_quiz.xml)
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <TextView
        android:id="@+id/question_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="24dp" />
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/true_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/true_button"/>
        <Button
            android:id="@+id/false_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/false_button"/>
    </LinearLayout>
    <Button
        android:id="@+id/cheat_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/cheat_button"/>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/pre_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/pre_button"
            android:drawableLeft="@drawable/arrow_left"/>
        <ImageButton
            android:id="@+id/next_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/arrow_right"
            android:contentDescription="@string/next_button"/>
    </LinearLayout>
</LinearLayout>

activity_quiz.xml rendering

  • Create string resources

It is better not to hard-code the text information of the settings component, such as: android:text="True". Better practice is to place text content in a separate string resource XML file and reference them, such as: android: text="@string/true_button".

Find the app/res/values directory and open the string.xml file
Add string resources

<resources>
    <string name="app_name">GeoQuiz</string>
    <string name="true_button">True</string>
    <string name="false_button">False</string>
    <string name="pre_button">Pre</string>
    <string name="next_button">Next</string>
    <string name="correct_toast">Correct!</string>
    <string name="incorrect_toast">Incorrect!</string>
    <string name="question_oceans">The Pacific Ocean is larger than
the Atlantic Ocean.</string>
    <string name="question_mideast">The Suez Canal connects the Red Sea
and the Indian Ocean.</string>
    <string name="question_africa">The source of the Nile River is in Egypt.</string>
    <string name="question_americas">The Amazon River is the longest river in the Americas.</string>
    <string name="question_asia">Lake Baikal is the world\'s oldest and deepest
freshwater lake.</string>
    <string name="warning_text">Are you sure you want to do this?</string>
    <string name="show_answer_button">SHOW ANSWER</string>
    <string name="cheat_button">CHEAT!</string>
    <string name="judgment_toast">Cheating is wrong.</string>
    <string name="fist_page">This is the first page!</string>
</resources>

2. From Layout XML to View Objects

  • After the instance of activity subclass is created, the onCreate(Bundle) method will be invoked, and the user interface needs to be acquired and managed. SetContentView (int layout ResID) can be called again. According to the input layout resource ID parameters, the specified layout view is generated and placed on the screen. The components contained in the layout file are instantiated with their respective attribute definitions.
public class QuizActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_quiz);
    }
}
  • Resource and Resource ID
  1. Use the resource ID to get the corresponding resources in the code. The resource ID of activity_quiz.xml layout is R.layout.activity_quiz.
  2. Place all current resources in R.java files. Switch to the Project view and expand the directory app/build/generated/source/r.debug to see. R.java files are automatically generated during the compilation of Android projects. After modifying the layout or strings and other resources, the application needs to be run again before it can be updated.
  3. Add a resource ID for the required components. Such as: android:id="@+id/idName".
  • Application of Components
    private Button mTrueButton;//Add member variables to activity_quiz.java
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ......
         mTrueButton=(Button)findViewById(R.id.true_button);//Reference component
         mTrueButton.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {
                //Setting up listening events
            }
        });
    }
   

3. Create prompt messages

Android toast is a short pop-up message used to notify users. The following method of calling the Toast class can create toast:

public static Toast makeText(Context context,int resId,int durattion)
  • The Context parameter is usually an instance of Activity (Activity itself is a subclass of Context).
  • The second parameter is toast to display the resource ID of the string message.
  • The third parameter is used to specify the residence time of the toast message. Usually one of the Toast constants.
//For example
Toast.makeText(QuizActivity.this,R.string.incorrect_toast,Toast.LENGTH_SHORT).show();

4. Android and MVC Design Patterns

  • The application object is divided into three parts according to the categories of model, controller and view. Android Application Based on Model-
    The architecture pattern of Model-View-Controller (MVC) is designed. MVC design pattern shows that any object applied in the final analysis belongs to one of the model objects, view objects and control objects.

  • We use QuizActivity to create Question array objects. Then, by interacting with TextView and three Button s, geographic knowledge questions are displayed on the screen and feedback is given based on the user's answers, as shown in Figure 2-4.

  • Model Layer Question Class Code
public class Question {
    private int mTextResId;//Save the resource ID of the Geographic Knowledge Problem String. Resource ID is always int type
    private boolean mAnswerTrue;//Question answer

    public Question(int textResId,boolean answerTrue){
        mTextResId=textResId;
        mAnswerTrue=answerTrue;
    }

    public int getTextResId() {
        return mTextResId;
    }

    public void setTextResId(int textResId) {
        mTextResId = textResId;
    }

    public boolean isAnswerTrue() {
        return mAnswerTrue;
    }

    public void setAnswerTrue(boolean answerTrue) {
        mAnswerTrue = answerTrue;
    }
}

Generating getter and setter methods for member variables with prefix m

First, configure the m prefix of Android Studio to identify member variables.
Open the Android Studio preferences dialog box (Mac users select the Android Studio menu, Windows users select File_
Settings menu. Expand the Editor and Code Style options, respectively, and select the Code Generation option page under the Java option. In the Naming form, select the fields row and add m as the prefix for fields. To add the static variable prefix s, add s as the prefix of Static Fields. The following diagram.

  • Controller layer QuizActivity.java
public class QuizActivity extends AppCompatActivity {
    private ImageButton mNextButton;

    private TextView mQuestionTextView;

    private Question[] mQuestionBank=new Question[]{
            new Question(R.string.question_oceans,true),
            new Question(R.string.question_mideast,false),
            new Question(R.string.question_africa,false),
            new Question(R.string.question_americas,true),
            new Question(R.string.question_asia,true)
    };

    private int mCurrentIndex=0;
    
}

5. Adding Picture Resources

1.Add images to drawable In the corresponding directory, the suffix is named.png,.jpg,.gif Documents automatically get resources ID
  • mdpi:Medium Pixel Density Screen(About 160 dpi)
  • hdpi:High Pixel Density Screen(About 240 dpi)
  • xhdpi:Ultra-high Pixel Density Screen(About 320 dpi)
  • xxdpi:Ultra-high Pixel Density Screen(About 480 dpi)
2. stay XML Reference resources in files
  • by next Button to add pictures(activity_quiz.xml)
 <Button
          android:id="@+id/next_button"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@string/next_button"
          android:drawableLeft="@drawable/arrow_righ
          android:drawablePadding="4dp"/>

* The definition starting with @string/ is to refer to string resources*

* The definition starting with @drawable/ is to refer to drawable resources*

The ImageButton component inherits from the ImageView. Button components inherit from TextView. ImageView and TextView inherit from View

ImageButton components can also be replaced by Button components. Delete the text and drawable attribute definitions of the next button and add the ImageView attribute.

 <ImageButton
          android:id="@+id/next_button"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:src="@drawable/arrow_right"
          android:contentDescription="@string/next_button"/>

6. The life cycle of activity

When the device rotates, the system destroys the current QuizActivity instance and creates a new QuizActivity instance. So every time the user of the rotating device starts with the first question, it's time to correct the defect.

  • Creating horizontal pattern layout

Right-click the res directory and select New - > Android resource directory. Select layout for resource type, keep the main option of Source set unchanged, select Orientation in the list of resources to be selected, and then click the > button to move it to the selected resource feature area.

Finally, confirm that the Landscape option is selected in the Screen orientation drop-down list and ensure that the directory name is displayed as layout-land.

The - land suffix name here is another example of the use of configuration modifiers. Android relies on the configuration modifier of the res subdirectory to locate the best resource to match the current device configuration. When the device is in the horizontal direction, Android will find and use the layout resources in the res/layout-land directory. In other cases, it defaults to using layout resources in the res/layout directory.

  • Copy the activity_quiz.xml file in the res/layout directory to the res/layout-land directory.

Note: The file names of the two layout files must be the same so that they can be referenced with the same resource ID

  • Horizontal pattern layout modification (layout-land/activity_quiz.xml)

FrameLayout replaces the top-level Linear Layout. FrameLayout is the simplest ViewGroup component, which arranges the location of its subviews anyway. The placement of FrameLayout subviews depends on their respective android:layout_gravity attributes.

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/question_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:padding="24dp" />
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical|center_horizontal"
        android:orientation="horizontal">

        <Button
            android:id="@+id/true_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/true_button"/>
        <Button
            android:id="@+id/false_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/false_button"/>
    </LinearLayout>
    <Button
        android:id="@+id/cheat_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|center"
        android:text="@string/cheat_button"/>

    <Button
        android:id="@+id/pre_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|left"
        android:text="@string/pre_button"
        android:drawableLeft="@drawable/arrow_left"
        android:drawablePadding="4dp"/>
    <ImageButton
        android:id="@+id/next_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|right"
        android:src="@drawable/arrow_right"
        android:contentDescription="@string/next_button"/>
</FrameLayout>
  • Save data for device rotation

Override the following Activity methods

protected void onSaveInstanceState(Bundle outState)
  • This method is usually called by the system before the onStop() method unless the user presses the back key.
  • The default implementation of this method requires all active views to store their data state in Bundle objects. Bundle is a structure that stores the mapping relationship (key-value pairs) between string keys and defined type values.
public class QuizActivity extends AppCompatActivity {
    ......
    private int mCurrentIndex=0;
    private static final String KEY_INDEX="index";
    @Override
    protected void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
      
        savedInstanceState.putInt(KEY_INDEX,mCurrentIndex);
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_quiz);
        
        if(savedInstanceState!=null){
            mCurrentIndex=savedInstanceState.getInt(KEY_INDEX,0);
        }
        ......
    }
    ......
}

7. log

public static int d(String tag,String msg)//Output log information d:debug

The first parameter of a method is usually passed in as a TAG constant with a class name value

public class QuizActivity extends AppCompatActivity {
    private static final String TAG="QuizActivity";
    ......
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        Log.d(TAG,"onCreate(Bundle) called");
        
        setContentView(R.layout.activity_quiz);
      
        ......
    }
}
log level Method Explain
ERROR Log.e(...) error
WARNING Log.w(...) warning
INFO Log.i(...) Informational message
DEBUG Log.w(...) Debug output
VERBOSE Log.v(...) For development only

All logging methods have two parameter signatures: tag and msg parameters of string type, and Throwable instance parameters in addition to tag and msg parameters.

9. Second activity

The new activity will bring a second user interface that will make it easier for users to peek at the answers to questions.

Definition of the layout component of the second activity (activity_cheat.xml)

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context="com.example.mdx.studyworks.CheatActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="24dp"
        android:text="@string/warning_text"/>
    <TextView
        android:id="@+id/answer_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="24dp"
        tools:text="Answer"/>
    <Button
        android:id="@+id/show_answer_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/show_answer_button"/>

</LinearLayout>

activity_cheat.xml rendering

  • Note the TextView component for displaying answers, which has a special namespace for tools and tools:text attributes. The namespace can override any property of a component. In this way, you can see the effect in the preview, while the Answer text will not appear at run time.
  • All activities of an application must be declared in the manifest configuration file so that the operating system can find them.
//Declare CheatActivity in manifest configuration file
<activity android:name=".CheatActivity">
        </activity>

Start the activity

public void startActivity(Intent intent)

When activity calls the startActivity(Intent) method, the call request is actually sent to the ActiveyManager of the operating system. Activity Manager is responsible for creating an Activity instance and calling its onCreate(Bundle) method

public Intent(Context pageContext,Class<?> cls)

The Class type parameter passed into the method tells ActivityManager which activity to start

The Context parameter tells Activity Manager where to find it

    mCheatButton=(Button)findViewById(R.id.cheat_button);
    mCheatButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //Start CheatActivity from QuizActivity
            Intent i=new Intent(QuizActivity.this,CheatActivity.class);
            startActivity(i);   
        }
    });

Data Transfer Between Activities

  • Use intent extra

Add extra data information to intent and call the Intent.putExtra(...) method

public Intent putExtra(String name,boolean value)
 Intent i=new Intent(QuizActivity.this,CheatActivity.class);
 i.putExtra(EXTRA_ANSWER_IS_TRUE,answerIsTrue);
 startActivity(i)

Getting data from extra

public boolean getBooleanExtra(String name,boolean defaultValue)
 mAnswerIsTrue=getIntent().getBooleanExtra(EXTRA_ANSWER_IS_TRUE,false);

The Activity.getIntent() method returns the Intent object forwarded by the startActivity(Intent) method.

  • Get the return result from the subactivity
//Father activity
/*The second parameter is the request code.*/
public void startActivityForResult(Intent intent,int requestCode)

//There are two ways for child activity to send back information to parent activity
public final void setResult(int resultCode)
public final void setResult(int resultCode,Intent data)

resultCode can be any of the following predefined constants

  • Activity.RESULT_OK, or 1
  • Activity.RESULT_CANCELED, or 0

If you need to customize the result code, you can also use another constant: RESULT_FIRST_USER

//Father, QuizActivity
 private static final int REQUEST_CODE_CHEAT=0;
 
 mCheatButton.setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View v) {
            boolean answerIsTrue=mQuestionBank[mCurrentIndex].isAnswerTrue();
            
            Intent i=new Intent(QuizActivity.this,CheatActivity.class);
            i.putExtra(EXTRA_ANSWER_IS_TRUE,answerIsTrue);
            startActivityForResult(i,REQUEST_CODE_CHEAT);
        }
});
//Processing returned results
@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        //super.onActivityResult(requestCode, resultCode, data);
        //Result code inconsistency
        if (resultCode!= Activity.RESULT_OK){
            return;
        }
        //The result code is consistent
        if (requestCode==REQUEST_CODE_CHEAT){
            if (data==null){
                return;
            }
            //Analytic result intent
            mIsCheater=data.getBooleanExtra(EXTRA_ANSWER_SHOW,false);
            
        }
    }
//Son, CheatActivity
 Intent data=new Intent();
 data.putExtra(EXTRA_ANSWER_SHOW,isAnswerShown);
 setResult(RESULT_OK,data);//Set the return result
 

10. Use and management of activity

Designated as the first activity of the application

<!--Specify the first activity yes QuizActivity-->
<activity android:name=".QuizActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>

Posted by Dark57 on Fri, 24 May 2019 13:04:25 -0700