Android application development study notes (2 of 2, from hitwh)

Android application development

Attention! Since the pictures in the article are uploaded with one click through Typora, there are still bugs in this function, which can easily lead to confusion in the order of the pictures. , provided at the beginning of the article (1 of 2) Download the pdf resource of the original article. It is recommended to download the pdf and watch it, or contact me in the comment area to get other download links.

Article directory

Chapter 6 Intent

1 Introduction to Intent

Problem solved: How to start other activities and achieve one/two-way communication between them

Intent introduction
  1. Intent is a message passing mechanism between components. It is a complete description of an action: including the action generating component, the receiving component and the transferred data information.

    image-20230523220618321
  2. The main purpose of Intent is to start Activity and Service and publish Broadcast messages on the Android system.

    image-20230523220659742

2 Use Intent to start Activity [display and implicit]

show start
  1. Concept: Specify the Activity class to be started in the Intent.

  2. Example:

    image-20230523220755060
Implicit start
  • illustrate:

    • There is no need to specify which Activity to start, but the Android system determines which Activity to start based on the action and data of the Intent.

    • For example, if you want to start a browser but don't know which Activity should be started, you can use the implicit start of Intent, and the Android system will decide which Activity to start to receive the Intent.

    • Implicitly started activities can be the built-in activities of the Android system, the activities of the program itself, or the activities of third-party applications.

  1. Implicit startup example 1: Start the browser to open a URL

    image-20230523220904456
  2. Implicit startup example 2: Open the player to play music

    image-20230523221210335
    • Solution to the error problem when playing music example in 7.0:

      • 报错:FileUriExposedException: …exposed beyond app throughIntent.getData()

      • Reason: According to the requirements of Android N, if the Intent of the Uri in the file:// format leaves the application, it will cause a FileUriExposedException exception. To share files between applications, a Uri in the content:// format should be sent and the Uri should be granted temporary access. The FileProvider class implements this method.

      • Solution: Not recommended

        image-20230523221445197
    • Common Intent actions

      image-20230523221550582 image-20230523221612126
  3. Implicit startup example 3: example of program making a phone call

    • Add permissions in AndroidManifest.xml:

      <uses-permission android:name="android.permission.CALL_PHONE" />
      
    • Core program code:

      Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:18908643860"));
      startActivity(intent);
      
    • Permission application (after 6.0): See the code below

      image-20230523221918156 image-20230523221938312
    • Add v4 dependency (In Android development, adding v4 dependency is to use the classes and methods in the Android Support Library. The Android Support Library is a set of libraries that can help you use the latest API functions on older versions of the Android platform. The v4 library is one of them A library that contains many useful classes and methods, such as Fragment, ViewPager, NotificationCompat, etc.), I don’t think this method will be tested

      image-20230523225523104 image-20230523225642391

3 Data transfer between activities

Overall picture
image-20230523225921467
One-way data transfer
  1. A uses Bundle to transfer data to B: ★★★

    image-20230523230044070 image-20230523230034718
  2. About Bundle

    • The Bundle class is a class that stores and manages key-value pairs, and is mostly used to transfer values ​​between Activities.

    • Usage examples:

      image-20230523230131776
    • Some methods of Bundle class:

      clear(): Clear all saved data in this Bundle map.

      clone(): Clone the current Bundle

      containsKey(String key): Returns the value of the specified key

      getString(String key): Returns the characters of the specified key

      isEmpty(): Returns true if this bundle map is empty

      putString(String key, String value): Insert a string value of a given key

      remove(String key): Remove the value of the specified key

  3. putExtras(), getExtras() methods of Intent class

    • putExtras(Bundle): Add a Bundle object to the Intent
    • getExtras(): Get the Bundle object from the Intent
  4. One-way data transfer example 1 – passing normal data

image-20230523230711647 image-20230523230726499
  1. One-way data transfer example 2 – Passing object data

    • For the previous example, how to use a user object to pass data:

      image-20230523230828100
    • The key point is how the Bundle passes object data.

    • Bundle can pass objects, but only if this object needs to be serialized.

      What is serialization: Serialization is a mechanism used to process object streams to solve problems caused by read and write operations on object streams such as network propagation and disk reading and writing.

    • Bundle's putSerializable() method can store serialized object data (still in Key-Value form);

    • When receiving data, Bundle uses the getSerializable() method. To obtain data, you need to force-convert the original object type.

    • The specific process is as follows:

      (1) First serialize the User class (just implement the Serializable interface directly)

      image-20230523231057425

      (2) Sender: RegisterActivity main code

      image-20230523231117861

      (3) Receiving end: WelcomeActivity main code

      image-20230523231249223
Passing data in both directions
  1. General map

    image-20230523231358057
  2. A ↔ B working principle

image-20230523232344449
  1. B returns data to A’s core code framework ★★★
image-20230523232911832 image-20230523232943961
  1. Two-way data transfer example 1: A_Activity inputs two numbers, B_Activity sums and returns the value

    image-20230523233316859
    • A_Activity main code 1

      image-20230523233349370
    • B_Activity main code

      image-20230523233415369
    • A_Activity main code 2 – key event onActivityResult

      image-20230523233434913
  2. Two-way data transfer example 2 – Use the DatePicker control as an activity alone (self-study)

    image-20230523233507199
    • MainActivity main code 1

      image-20230523233559047
    • MainActivity main code 2

      image-20230523233615222
    • CalendarActivity main code 1

      image-20230523233652555
    • CalendarActivity main code 2

      image-20230523233710202

Chapter 7 Android Broadcast Mechanism

1 What is broadcasting

Overview
  1. In Android, broadcast is a mechanism widely used to transmit information between applications.
  2. The essence of a broadcast message is to send an Intent object using the sendBroadcast method (see Section 7.3 Custom Broadcasting for details).
  3. Two types of broadcasts:
    • System broadcast: messages sent by the system such as system startup is completed, a call is made, a text message is received, the phone is out of battery, etc.
    • Custom broadcast: Broadcast customized messages to applications
BroadcastReceiver
  1. BroadcastReceiver is a type of component that filters and responds to sent Broadcasts. It is one of the four major components of the Android system.

  2. BroadcastReceiver generally needs toregister in AndroidManifest.xml

    image-20230524000054038

2 system broadcast

Overview
  1. System broadcast is a broadcast sent by the Android system.
  2. For example, the system startup is completed, the system is shut down, a call is made, a text message is received, the phone is out of battery, a new application is installed, headphones are inserted into the headphone jack, the device has insufficient memory, the screen is turned off, etc.
System broadcast example 1: Play shutdown music when the phone is turned off
  1. Preparation: Create a new Module (named TestBroadcast)

    • Create a new raw folder under the res folder

    • Copy the music files to the raw folder

      image-20230524000219653
  2. Create a broadcast receiverBroadcastReceiver

    image-20230524000316179
    • Generated MyReceiver.java code framework:

      image-20230524000435995
  3. Handle broadcast: add processing code in onReceive:

    image-20230524000504211
  4. Register receiver: (static registration)

    Registration: Tell the system what kind of broadcast message this BroadcastReceiver wants to receive (Intent-filter)

    Add registration information (red part) in the AndroidManifest.xml file

    image-20230524001107139
  5. Permission settings: Some broadcasts require permission support, this example does not require it.

    If you need to add permissions, add them in AndroidManifest.xml, for example:

    image-20230524001154271
  6. Test run: First run MainActivity and install the app into the phone (tell the system that there is a BroadcastReceiver); then lock the screen and music will play.

  7. Partial system broadcast

    image-20230524001503090
Example 2: Monitor incoming calls (outgoing calls)
  1. Add a broadcast to Receiver to receive calls.

    image-20230524001539020
  2. Add permissions to the app to handle making calls

    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
    
  3. Supplement: Simulator after AS 6.0

    image-20230524001757288
  4. Modify Receiver code

    image-20230524001905404

3 Custom broadcast

The main steps
  1. Send broadcast message

    At the broadcast sending end (such as the Activity of an APP), load the information into an Intent object (containing a custom message identification string, the value is arbitrary, as long as it can ensure uniqueness), and then sendBroadcast(intent) broadcasts the Intent. .

    image-20230524002120847
  2. receive broadcast

    The receiving end creates Broadcast Receiver

    • Static registration: Register Receiver in AndroidManifest.xml and add intent-filter

      image-20230524002227995
    • Dynamic registration: code implementation registration

      image-20230524002242248
  3. The receiving end processes broadcast messages: onReceive() method

    image-20230524002347750
  4. About the message broadcast identification string:

    • Message broadcast identification string,Customized value, only needs to be unique

    • This logo will be used in 3 places later:

      • When sending a broadcast: used to create an Intent object, Intent intent = new Intent("broadcast identification string");
      • When registering in the manifest, use: as the action name value of the intent-filter of the BroadcastReceiver
      • When processing messages: Used in the onReceive() method to determine the message type.
    • Usually, the identification string can also be defined as a symbolic constant, such as:

      final String BROADCAST_ACTION_NAME = “如 wust.zz.mybroadcast";
      
Custom broadcast example (static registration)
  1. General map

    image-20230524002624032
  2. Sender app: MainActivity main code

    image-20230524002640515
  3. Receiver app: MyReceiver main code

    image-20230524002700764
  4. MyReceiver configuration (static registration)

    AndroidManifest.xml file: red part

    image-20230524002733368
  5. Supplement: Android8.0 custom broadcast cannot be received problem solved

    • Method 1: Use dynamic broadcast instead of static broadcast

    • Method 2: Keep the original static broadcast, but add the Component parameter to the intent:

      image-20230524002834501

Appendix: SMS blacklist example

Overview
  1. Monitor SMS text messages (SMS, Short Messaging Service)

    • If the text message sent by the other party contains the "@echo" string, the "denyyou!" message will be automatically sent back and the number will be blacklisted.
  2. BroadcastReceiver uses dynamic registration

    image-20230524003122649
MainActivity interface (activity_main.xml)
<ToggleButton
    android:id="@+id/toggleButton1" android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_alignParentLeft="true" 
    android:layout_alignParentTop="true" 
    android:layout_marginLeft="74dp" 
    android:layout_marginTop="44dp"
    android:text="监控SMS" 
    android:textOff="SMS监控已关闭" 
    android:textOn="SMS监控已开启" />
SMSReceiver code
image-20230524003441180 image-20230524003456563
Get text message instructions
image-20230524003530986
AndroidManifest.xml adds SMS permissions
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
MainActivity main code
image-20230524003622369

Chapter 8 Service

1 What is Service

  1. Service is one of the four major components of the Android system. It is a long-life-cycle service program that has no visual interface and runs in the background.

    image-20230524003756058

2 Service type

Started
  1. Started: often used inside applications

  2. The Started form refers to the service that is started when an application component (such as Activity) is started through the startService() method. Once started, the service can run in the background indefinitely, even if the component that started it is destroyed.

  3. Basic Features:

    • Define service components in the application.

    • The service is started by calling startService(intent) and ended by stopService(intent).

    • You can call stopSelf() inside the service to stop it yourself.

    • Typically, a started service performs a single operation and does not return a result to the caller.

    • No matter how many times startService() is called, stopService() only needs to be called once to stop.

Bound bound
  1. Bound binding: used between applications
  2. The Bound form means that an application component is bound to a service by calling the bindService() method. Call unbindService() to close the connection.
  3. Once a service in the form of Bound is enabled, the caller is bound to the service. Once the caller exits, the service will be terminated.
  4. Multiple components can be bound to a service at the same time, but when all bindings are released, the service is destroyed.
Service life cycle
image-20230524004359260

3 Local service examples

Overview
  1. sample graph

    image-20230524004459973
  2. The main steps:

    • Preparation
    • CreateMusicService
    • main program
    • Function improvements
Preparation
  1. Create a new raw folder under the res folder

  2. Copy the music files to the raw folder

    image-20230524004556330
CreateMusicService
image-20230524004619386
  • MusicService code framework

    image-20230524004704822
  • MusicService code

    image-20230524004824291
Main program (main code)
image-20230524004853476
Functional improvements (self-study)
  • Added pause, replay, end (stop service) functions

    image-20230524005011423
  • Idea: Pass parameter values ​​to Service in Intent

    • Assumed parameter values:
      • 1 – Play
      • 2 – Pause
      • 3 – Replay
      • 0 – End (end service internally)
      • -1 – Exit (end services and activities externally)
  • Main interface activity_main.xml

    image-20230524005045959
  • MainActivity main code

    image-20230524005102406 image-20230524005120549 image-20230524005152005
  • MusicService main code

    image-20230524005218900 image-20230524005228814

4 Broadcast interaction

  • Start Service after clicking Button in Activity

    public void onClick(View v) {
          
          
        Intent intent = new Intent(this, CounterService.class);
        intent.putExtra("counter", counter); //counter用来计数
        startService(intent);
    }
    
  • CounterService.java

    public class CounterService extends Service {
          
           
        int counter; 
        @Override
        public IBinder onBind(Intent intent) {
          
          
            // TODO Auto-generated method stub
            return null;
        } 
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
          
          
            // TODO Auto-generated method stub
            counter = intent.getIntExtra("counter", 0);
            new Timer().schedule(new TimerTask() {
          
          
                @Override
                public void run() {
          
          
                    // TODO Auto-generated method stub
                    Intent counterIntent = new Intent();
                    counterIntent.putExtra("counter", counter);
                    counterIntent.setAction("com.example.counter.COUNTER_ACTION");
                    sendBroadcast(counterIntent);
                    counter++;
                }
            }
            return START_STICKY;
        } 
    }
    
  • Start a timer in Service's onStartCommand(), add 1 to the counter every second, and send the counter through broadcast. After the CounterReceiver in the Activity receives the broadcast, take out the counter and send the counter through the handler.

    // 广播接收器,定义在Activity中 
    class CounterReceiver extends BroadcastReceiver {
          
          
    	Handler handler;
    	CounterReceiver(Handler handler){
          
          
    		this. handler = handler;
    	}
        @Override
        public void onReceive(Context context, Intent intent) {
          
          
            counter = intent.getIntExtra("counter", 0);
    	    handler.sendEmptyMessage(counter);
        }
    }
    //运行程序,点击按钮开始计时
    
  • Set it to the Button through the Handler in the Activity. The Button should be designed as a global variable of the Activity and initialized in onCreat:

    CounterReceiver receiver;
    Button start;
    Handler handler = new Handler(){
          
          
    	 @Override
    	 public void handleMessage(Message msg){
          
          
    		start. setText(String.valueOf (msg.what)) 
    		super.handleMessage(msg); 
    	} 
    }
    
  • In Activity's onCreat

    Receiver = new CounterReceiver(handler)
    start = (Button)findViewById(R.id.start)
    
  • sample graph:

    image-20230524010953805
  • I encountered a problem during the running of the program. Please explain it here.

    • The broadcast class is defined in Activity and is an internal class of Activity. When this internal class is statically registered, the program will crash. The reason is that if the internal broadcast class is statically registered, it must be a static internal class.
    • However, if it is a static inner class, you can only access the static member variables of the outer class, so it is recommended to use dynamic registration for internal broadcast classes.
    • Moreover, this type of broadcast is generally only used within the program, and there is no need to continue to receive broadcasts after the process ends.
  • The interaction between Activity and Service through broadcasting is simple and easy to implement.

    • The disadvantage is that sending or not broadcasting is subject to system constraints. The system will give priority to sending system-level broadcasts, and custom broadcast receivers may be delayed.
    • There cannot be any time-consuming operations in the broadcast, otherwise the program will become unresponsive.
  • Dynamically register the receiver in Activity, such as placing it in onCreat:

    IntentFilter filter = new IntentFilter();
    filter.addAction("com.example.counter.COUNTER_ACTION ");
    BroadcastReceiver receiver = new MyReceiver();
    registerReceiver( receiver , filter);
    
  • In addition, when the Activity is destroyed, log out (close) the broadcast:

    unregisterReceiver(receiver);
    
  • Further learning: About creating and calling remote services

    reference:

    • http://www.apkbus.com/android-131250-1-1.html
    • http://liangruijun.blog.51cto.com/3061169/653344/

Chapter 9 1+ Simple Data Storage and Access (Simple) (SharedPreference)

0 Simple data storage

  1. Applications generally allow users to define configuration information, such as interface background color, font size and font color, etc.
  2. Use SharedPreferences to save the user's customized configuration information, and automatically load these customized configuration information when the program starts.

1 Simple storage

Overview
  1. The information entered by the user on the interface is saved when the Activity is closed. When the application is reopened, the saved information will be read out and re-presented on the user interface
SharedPreferences
  1. SharedPreferences is a lightweight way to save data.

    • NVP (Name/Value Pair, name/value pair) can be saved in the Android file system through SharedPreferences, and SharedPreferences completely blocks the operation process of the file system.
    • Developers only save and read NVP by calling SharedPreferences.
  2. SharedPreferences not only saves data, but also enables data sharing between different applications.

    • SharedPreferences supports three access modes
      • Private (MODE_PRIVATE): Only the creating program has permission to read or write it.
      • Global read (MODE_WORLD_READABLE): Not only the creating program can read or write to it, but other applications also have permission to read operations, but do not have permission to write operations.
      • Global write (MODE_WORLD_WRITEABLE): The creation program and other programs can write to it, but do not have read permission.
  3. Before using SharedPreferences, first define the access mode of SharedPreferences.

    • The following code defines the access mode as private mode:

      public static int MODE = MODE_PRIVATE;
      
    • Sometimes it is necessary to set the access mode of SharedPreferences to either global reading or global writing, so the two modes need to be written in the following way:

      public static int MODE = Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE;
      
  4. Define the name of SharedPreferences

    • This name is the same as the file saved in the Android file system. Therefore, as long as the NVP content has the same SharedPreferences name, it will be saved in the same file

      public static final String PREFERENCE_NAME = "SaveSetting";
      
    • In order to use SharedPreferences, you need to pass the access mode and SharedPreferences name as parameters to the getSharedPreferences() function and obtain the SharedPreferences object.

      SharedPreferences sharedPreferences = getSharedPreferences(PREFERENCE_NAME, MODE);
      
  5. Modify SharedPreferences

    • After obtaining the SharedPreferences object, you can modify the SharedPreferences through the SharedPreferences.Editor class, and finally call the commit() function to save the modifications.

    • SharedPreferences widely supports various basic data types, including integer, Boolean, floating point, long, etc.

      SharedPreferences.Editor editor = sharedPreferences.edit();
      editor.putString("Name", "Tom");
      editor.putInt("Age", 20);
      editor.putFloat("Height", 1.67);	//这里PPT没有float的内容,猜测是这样
      editor.commit();
      
  6. Read SharedPreferences

    • If you need to read data from the saved SharedPreferences, you also need to call the getSharedPreferences() function, specify the name of the SharedPreferences you need to access in the first parameter of the function, and finally obtain the data saved in SharedPreferences through the get<Type>() function. NVP.

      SharedPreferences sharedPreferences = getSharedPreferences(PREFERENCE_NAME, MODE);
      String name = sharedPreferences.getString("Name","Default Name");
      int age = sharedPreferences.getInt("Age", 20);
      float height = sharedPreferences.getFloat("Height",);
      
      • The first parameter of the get<Type>() function is the name of the NVP.
      • The second parameter is the default value used when the value cannot be obtained.
Example

The SimplePreferenceDemo example introduces the file saving location and saving format of SharedPreferences in detail.

  1. The following figure is the user interface of the SimplePreferenceDemo example

    The information entered by the user on the interface will be saved through SharedPreferences when the Activity is closed. When the application is reopened, the information saved in SharedPreferences will be read and re-presented on the user interface.

    image-20230524102128850
  2. File information

    • After the SimplePreferenceDemo example is run, view the data under /data/data through FileExplorer. Android creates a directory with the same name as the package for each application to save the data generated by the application, including files, SharedPreferences files, databases, etc.

    • The SharedPreferences file is saved in the /data/data/<package name>/shared_prefs directory.

    • In this example, a file named SaveSetting.xml is generated in the shared_prefs directory:

      image-20230524102435288
      • This file is the file that saves SharedPreferences. The file size is 170 bytes, and the permissions under Linux are "-rw-rw-rw"

        In the Linux system, file permissions respectively describe the restrictions on file operations by the creator, users in the same group, and other users.

        • x means executable, r means readable, w means writable, d means directory, - means ordinary file. Therefore, "-rw-rw-rw" means that SaveSetting.xml can be read and written by the creator, users in the same group, and other users, but cannot be executed.
        • The generation of such file permissions is related to the access mode of SharedPreferences set by the programmer. The permissions of "-rw-rw-rw" are the result of "global read + global write".
        • If the access mode of SharedPreferences is set to private, the file permissions will become "-rw-rw —", which means that only the creator and users in the same group have permission to read and write the file.
    • The SaveSetting.xml file is information saved in XML format. The content is as follows

      <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
      <map>
      	<float name="Height" value="1.81" />
      	<string name="Name">Tom</string>
      	<int name="Age" value="20" />
      </map>
      
  3. Specific functions and related codes

    • The SimplePreferenceDemo example calls the loadSharedPreferences() function in the onStart() function to read the name, age and height information saved in SharedPreferences and display it on the user interface.

      • When the Activity is closed, call saveSharedPreferences() in the onStop() function to save the information on the interface.

      • The complete code of SimplePreferenceDemo.java:

        package edu.hrbeu.SimplePreferenceDemo;
         
        import android.app.Activity;
        import android.content.Context;
        import android.content.SharedPreferences;
        import android.os.Bundle;
        import android.widget.EditText;
         
        public class SimplePreferenceDemo extends Activity {
                  
                  
        	
        	private EditText nameText;
        	private EditText ageText;
        	private EditText heightText;
        	public static final String PREFERENCE_NAME = "SaveSetting";
        	public static int MODE = Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE;
        	
        	@Override
        	public void onCreate(Bundle savedInstanceState) {
                  
                  
        		super.onCreate(savedInstanceState);
        		setContentView(R.layout.main);
        		nameText = (EditText)findViewById(R.id.name);
        		ageText = (EditText)findViewById(R.id.age);
        		heightText = (EditText)findViewById(R.id.height);
        	}
           
            @Override
        	public void onStart(){
                  
                  
        		super.onStart();
        		loadSharedPreferences();
        	}
        	@Override
        	public void onStop(){
                  
                  
        		super.onStop();	
        		saveSharedPreferences();
        	}
            
        	private void loadSharedPreferences(){
                  
                  
        	  	SharedPreferences sharedPreferences = getSharedPreferences(PREFERENCE_NAME, MODE);
        		String name = sharedPreferences.getString("Name","Tom");
        		int age = sharedPreferences.getInt("Age", 20);
        		float height = sharedPreferences.getFloat("Height",);
         		nameText.setText(name);
        		ageText.setText(String.valueOf(age));
        		heightText.setText(String.valueOf(height));    	
        	}
            
            private void saveSharedPreferences(){
                  
                  
        		SharedPreferences sharedPreferences = getSharedPreferences(PREFERENCE_NAME, MODE);
        		SharedPreferences.Editor editor = sharedPreferences.edit();
        		    
        		editor.putString("Name", nameText.getText().toString());
        		editor.putInt("Age", Integer.parseInt(ageText.getText().toString()));
        		editor.putFloat("Height", Float.parseFloat(heightText.getText().toString()));
        		editor.commit();
        	}
        }
        
    • The example SharePreferenceDemo will illustrate how to read SharedPreferences data saved by other applications.

      • The figure below is the user interface of the SharePreferenceDemo example.

      • The sample will read the information saved by the SimplePreferenceDemo sample and display it on the user interface when the program starts.

        image-20230524103140761
    • The core code of the SharePreferenceDemo example

      image-20230524103217095 image-20230524110121702
  4. Three conditions must be met to access SharedPreferences of other applications:

    • The sharer needs to set the access mode of SharedPreferences to global read or global write.
    • The visitor needs to know the sharer's package name and the name of the SharedPreferences to obtain the SharedPreferences object through the Context.
    • Visitors need to know exactly the name and data type of each data in order to read the data correctly.

2 file storage

Overview
  1. Android uses a Linux-based file system.
  2. Program developers can create and access the program's own private files.
  3. Raw files and XML files saved in the resources directory can also be accessed.
  4. You can also save files in external storage devices such as SD cards.
internal storage
  1. File writing and reading on internal memory

    image-20230524103912679
  2. The Android system allows applications to create private files that can only be accessed by themselves. The files are stored on the device's internal memory in the /data/data/<package name>/files directory under Linux systems.

  • The Android system not only supports standard Java IO classes and methods, but also provides functions that simplify the process of reading and writing streaming files.
  • The two main functions introduced:
    • openFileOutput()
    • openFileInput()
  1. openFileOutput() function

    • The openFileOutput() function opens an application's private file in preparation for writing data. If the specified file does not exist, a new file is created.

    • The syntax format of the openFileOutput() function is as follows:

      public FileOutputStream openFileOutput(String name, int mode)
      
      • The first parameter is the file name. This parameter cannot contain slashes describing the path.
      • The second parameter is the operating mode.
    • The return value of the function is of FileOutputStream type.

    • The Android system supports four file operation modes:

      image-20230524104208645
    • The sample code for creating a new file using the openFileOutput() function is as follows:

      String FILE_NAME = "fileDemo.txt";  //定义了建立文件的名称fileDemo.txt
      FileOutputStream fos = openFileOutput(FILE_NAME,Context.MODE_PRIVATE)  //使用openFileOutput()函数以私有模式建立文件
      String text =Some data”;
      fos.write(text.getBytes());  //调用write()函数将数据写入文件
      fos.flush();  //调用flush()函数将所有剩余的数据写入文件
      fos.close();  //调用close()函数关闭FileOutputStream
      
      • In order to improve the performance of the file system, when the write() function is generally called, if the amount of data written is small, the system will save the data in the data buffer, and then write the file all at once when the amount of data accumulates to a certain extent. middle.
      • It can be seen from the above that before calling the close() function to close the file, be sure to call the flush() function to write all the data in the buffer to the file.
  2. openFileInput() function

    • The openFileInput() function opens an application's private file in preparation for reading data.

    • The syntax format of the openFileInput() function is as follows:

      public FileInputStream openFileInput (String name)
      
      • The first parameter is also the file name, and slashes describing the path are also not allowed.
    • The sample code for using the openFileInput () function to open an existing file is as follows:

      String FILE_NAME = "fileDemo.txt";
      FileInputStream fis = openFileInput(FILE_NAME);
       
      byte[] readBytes = new byte[fis.available()];
      while(fis.read(readBytes) != -1){
              
              
      }
      
      • The above two parts of code will encounter error prompts during actual use, because file operations may encounter various problems and eventually cause the operation to fail, so the code should use try/catch to catch possible exceptions.
  3. The InternalFileDemo sample demonstrates writing and reading files on internal memory.

    • InternalFileDemo sample user interface is shown in the figure:

      image-20230524104916033
    • Core code of the InternalFileDemo example:

      OnClickListener writeButtonListener = new OnClickListener() {
              
               
      	@Override
      	public void onClick(View v) {
              
              
      		FileOutputStream fos = null;	
      		try {
              
              
      		      if (appendBox.isChecked()){
              
              
      		           fos = openFileOutput(FILE_NAME,Context.MODE_APPEND);
      	                        }
                                         else {
              
              
      		          fos = openFileOutput(FILE_NAME,Context.MODE_PRIVATE);
      		      }
      		String text = entryText.getText().toString();
      		fos.write(text.getBytes());
      		labelView.setText("文件写入成功,写入长度:"+text.length());
      		entryText.setText("");
                                    } catch (FileNotFoundException e) {
              
              
                                                     e.printStackTrace();
      		}
      		catch (IOException e) {
              
              
      			e.printStackTrace();
      		}
      		finally{
              
              
      			if (fos != null){
              
              
      				try {
              
              
      					fos.flush();
      					fos.close();
      				} catch (IOException e) {
              
              
      					e.printStackTrace();
      				}
      			}
      		}
      	}
      };
      OnClickListener readButtonListener = new OnClickListener() {
              
               
      @Override
       	public void onClick(View v) {
              
              
       		displayView.setText("");
       		FileInputStream fis = null;
       		try {
              
              
      		            fis = openFileInput(FILE_NAME);
      		            if (fis.available() == 0){
              
              
      			   return;
      	                               }
      		             byte[] readBytes = new byte[fis.available()];
      		             while(fis.read(readBytes) != -1){
              
              
      		             }
      		             String text = new String(readBytes);
      		             displayView.setText(text);
      		              labelView.setText("文件读取成功,文件长度:"+text.length());
                                    } catch (FileNotFoundException e) {
              
              
                                                     e.printStackTrace();
      		}
      		catch (IOException e) {
              
              
      			e.printStackTrace();
      		}
      	}
      };
      
      • After the program is run, the newly created fileDemo.txt file is found in the /data/data/edu.hrbeu.InternalFileDemo/files/ directory.

      • fileDemo.txt text:

        image-20230524105441595
        • fileDemo.txt is analyzed from the perspective of file permissions. "-rw-rw—" indicates that the file is only allowed to be read and written by the file creator and users in the same group, and other users have no rights to use it.
        • The size of the file is 9 bytes and the saved data is "Some data"
external storage
  1. Android's external storage device refers to SD card (Secure Digital Memory Card), which is a memory card widely used in digital devices. Not all Android phones have SD cards, but the Android system provides a convenient way to access the SD card.

  2. The SD card is suitable for saving large-size files or files that do not require setting access permissions. It can save recorded large-capacity video files and audio files, etc.

    • The SD card uses the FAT (File Allocation Table) file system and does not support access mode and permission control. However, the privacy of files can be ensured through the control of file access permissions in the Linux file system.
    • The Android emulator supports SD cards, but there is no default SD card in the emulator. Developers must manually add the SD card image file in the emulator.
  3. Use the mksdcard tool in the <Android SDK>/tools directory to create an SD card image file. The command is as follows:

    mksdcard -l SDCARD 256M E:\android\sdcard_file
    
    • The first parameter -1 indicates that the following string is the label of the SD card, and the label of this newly created SD card is SDCARD.
    • The second parameter 256M indicates that the capacity of the SD card is 256 MB.
    • The last parameter indicates the storage location of the SD card image file. The above command saves the image in the sdcard_file file in the E:\android directory. After executing this command in CMD, the produced SD card image file can be found in the specified directory.
  4. If you want the Android emulator to automatically load the specified SD card when it starts, you also need to add the SD card loading command in the "Run Configurations" of the emulator.

    • Just specify the image file location in the SD card loading command.

    • SD card loading command:

      image-20230524105723436
  5. Test whether the SD card image loads correctly

    • After the simulator is started, use FileExplorer to upload a file to the SD card at will. If the file is uploaded successfully, it means that the SD card image has been successfully loaded.

    • A test file test.txt was successfully uploaded to the SD card and the file is displayed in the /sdcard directory.

      image-20230524105808587
  6. Programmatic access to SD card

    • First, you need to check whether the system's /sdcard directory is available.
    • If it is not available, it means that the SD card has been removed from the device. In the Android emulator, it means that the SD card image has not been loaded correctly.
    • If available, it is accessed directly by using the standard Java.io.File class.
  7. Save data on SD card

    • Generate 10 random decimals through the "Generate Random Number Sequence" button.
    • Save the produced data in the directory of the SD card through the "Write to SD Card" button.
    • The SDcardFileDemo example illustrates how to save data on an SD card.
  8. SDcardFileDemo example

    • user interface

      image-20230524110010947
    • After the SDcardFileDemo example is run, each time the "Write to SD Card" button is clicked, a new file will be produced in the SD card with different file names.

      • Files produced in SD card:

        image-20230524110044850
    • Core code of SDcardFileDemo example

      image-20230524110219083 image-20230524110238366
resource
  1. Program developers can store the original format files and XML files prepared during the program development stage in the /res/raw and /res/xml directories respectively, so that the application can access them at runtime.

    • Raw format files can be files in any format, such as video format files, audio format files, image files, data files, etc. When the application is compiled and packaged, all files in the /res/raw directory will retain their original formats. Change.
    • XML files in the /res/xml directory are generally used to save formatted data. When the application is compiled and packaged, the XML file will be converted into an efficient binary format, and will be accessed in a special way when the application is running.
  2. ResourceFileDemoExample

    • The ResourceFileDemo sample demonstrates how to access resource files while the program is running.

      • When the user clicks the "Read Raw File" button, the program will read the /res/raw/raw_file.txt file and display the content on the interface.
      image-20230524110426768
      • When the user clicks the "Read XML file" button, the program will read the /res/xml/people.xml file and display the content on the interface.

        image-20230524110532679
    • To read a raw format file, you first need to call the getResource() function to obtain the resource object, and then open the specified raw format file in the form of a binary stream by calling the openRawResource() function of the resource object. After reading the file, call the close() function to close the file stream.

      • The core code for reading raw format files in the ResourceFileDemo example is as follows:

        Resources resources = this.getResources();
        InputStream inputStream = null;
        try {
                  
                  
        	inputStream = resources.openRawResource(R.raw.raw_file);    
        	byte[] reader = new byte[inputStream.available()]; 
        	while (inputStream.read(reader) != -1) {
                  
                   
        	}
            displayView.setText(new String(reader,"utf-8")); 
        } catch (IOException e) {
                  
                  
        	Log.e("ResourceFileDemo", e.getMessage(), e); 
        } finally {
                  
                  
        	if (inputStream != null) {
                  
                   
        		try {
                  
                  
        			inputStream.close(); 
        		} catch (IOException e) {
                  
                   } 
        	}
        }
        
        • New String(reader, "utf-8") in line 8 of the code means instantiating a string from a byte array in UTF-8 encoding.
      • Program developers need to make sure that the /res/raw/raw_file.txt file uses UTF-8 encoding, otherwise garbled characters will be generated when the program is run. Confirmation method:

        • Right-click on the raw_file.txt file.

        • Select "Properties" to open the property setting box of the raw_file.txt file.

        • In the Text file encoding under the Resource column, select "Other: UTF-8".

          image-20230524111134519
    • XML files in the /res/xml directory will be converted into an efficient binary format

      • How to read XML files in the /res/xml directory while the program is running

        • First create a file named people.xml in the /res/xml directory.
        • The XML file defines multiple <person> elements. Each <person> element contains three attributes: name, age, and height, which represent name, age, and height respectively.
      • The code of the /res/xml/people.xml file is as follows:

        <people> 
        	<person name="李某某" age="21" height="1.81" /> 
        	<person name="王某某" age="25" height="1.76" /> 
        	<person name="张某某" age="20" height="1.69" /> 
        </people>
        
    • To read an XML format file, first obtain the XML parser XmlPullParser by calling the getXml() function of the resource object. XmlPullParser is the standard XML parser for the Android platform. This technology comes from an open source XML parsing API project XMLPULL.

      • The core code for reading XML files in the ResourceFileDemo example is as follows:

        image-20230524111511617 image-20230524111534940 image-20230524111552026
      • XML event types for XmlPullParser

        image-20230524111618923

Chapter 9 2++ Data Storage and Access (SQLite Example)

image-20230524111841475

1 ListView displays database data (ShowActivity)

ListView 2 key points
  1. Custom layout layout;

  2. Populate using SimpleCursorAdapter adapter: (for displaying database data)

    This adapter allows binding the data column of a Cursor (query result set) to the TextView or ImageView component in the ListView custom layout (see the code below for details)

    image-20230524112403877
  3. Detailed code explanation:

    • ListView customizes the layout and creates a new layout named listview.xml:

      image-20230524112444563
    • Use SimpleCursorAdapter to populate ListView, SimpleCursorAdapter basic method:

      image-20230524112546497
    • ShowAcitvity's OnCreate() main code:

      image-20230524112839870

2 Add recording function (InsertActivity)

image-20230524112956668
  1. ShowActivity "Add" button

    image-20230524113108634
  2. InsertActivity "Save" button

    image-20230524113144450 image-20230524113333413
  3. ShowActivity receives the postback information (the following code is parallel to onCreate)

    image-20230524113435762

3 Add ContextMenu menu to ListView: Delete + Edit (UpdateActivity)

The main steps
  1. Step 1: Create a new menu resource

    • Create a new menu directory under res

    • Create a new manage.xml file in the menu directory, code:

      image-20230524113633187
  2. Step 2: Create context menu (the following code is placed in ShowActivity, parallel to onCreate)

    image-20230524113707414
  3. Step 3: Add the context menu selection method (the following code is placed in ShowActivity, parallel to onCreateContextMenu)

    image-20230524113945191
  4. Step 4: Register the context menu to the ListView (End) (The following code is placed in onCreate in ShowActivity)

    image-20230524114028238
  5. Analysis of subsequent deletion and modification operations:

    • The key points of the two operations:

      • How to get the id value of the selected row and other field values ​​(name, age).
      • Delete: Use the id value as the condition for deleting records.
      • Modification: Pass the id value and other field values ​​to UpdateActivity for display and modification.
    • Key point code:

      image-20230524165040061
    • Specific code:

      • Delete operation delete(MenuItem item) method

        image-20230524165116701
      • Modify operations

        image-20230524165252238

        UpdateActivity: oncreat() code

        image-20230524165506477 image-20230524165526980 image-20230524165550979
      • ShowActivity receives postback information

        image-20230524165623811

Guess you like

Origin blog.csdn.net/m0_56942491/article/details/131734570