android Learning Notes - Broadcast Receiver Receiver Receiver Receiver Broadcasting Process (ip Dialer, sd Card Status, SMS, Application Installation and Unloading)

android has built-in many system-level broadcasts, such as a broadcast when the mobile phone is turned on, a broadcast when the battery power changes, a broadcast when the time or time zone changes, and so on. To receive these broadcasts, you need to use a broadcasting receiver. Here's a basic understanding of the process.

Catalog

IP Dialer:

Monitoring SD Card Status:

Short Message Monitor:

Unloading and installation of applications:

 

IP Dialer:

The interface that we want to implement is an ip dialer. For example, it will be cheaper to add prefix when making long-distance calls. Save the prefix. Then when making long-distance calls, as long as the prefix begins with 0, the prefix will be added automatically. For example, save the prefix 12345. Then call 0134679 and dial out is 123450134679. This is of no practical use for learning.

 

1. Defining a broadcasting receiver is equivalent to buying a radio.

public class OutGoingCallReceiver extends BroadcastReceiver

2. Configuration in the manifest file is equivalent to installing a battery.

<receiver android:name=".OutGoingCallReceiver" >

3. Move to a suitable channel.

<intent-filter>
        <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>

4. Remember to add permissions

<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />

 

 AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.ip_dialer">
    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android:name=".OutGoingCallReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

MainActivity.java

import android.Manifest;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private EditText et_number;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.PROCESS_OUTGOING_CALLS)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.PROCESS_OUTGOING_CALLS}, 1);
        }
        et_number = (EditText) findViewById(R.id.et_ipnumber);

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0) {
                    for (int result : grantResults) {
                        if (result != PackageManager.PERMISSION_GRANTED) {
                            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                                    Manifest.permission.PROCESS_OUTGOING_CALLS)) {
                                showPermissionDialog(permissions);
                            } else {
                                Toast.makeText(this, "You have denied permission. Please open permission manually in settings.", Toast.LENGTH_SHORT).show();
                            }
                            return;
                        }
                    }
                }
                break;
        }
    }

    private void showPermissionDialog(final String[] permissions) {
        AlertDialog.Builder dialog = new AlertDialog.Builder(this);
        dialog.setTitle("Tips!");
        dialog.setMessage("This privilege relates to sending text messages, such as rejection which needs to be opened manually in the settings.!");
        dialog.setCancelable(false);
        dialog.setPositiveButton("To grant authorization", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                ActivityCompat.requestPermissions(MainActivity.this, permissions, 1);
            }
        });
        dialog.setNegativeButton("refuse", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        });
        dialog.show();
    }

    // Click the button to save the ip number entered by the user
    public void onclick(View view) {
        String ipnumber = et_number.getText().toString().trim();
        // Save the current ipnumber in the sp
        SharedPreferences sp = getSharedPreferences("config", MODE_PRIVATE);
        // Get the editor for sp
        sp.edit().putString("ipnumber", ipnumber).commit();
        // Save successfully
        Toast.makeText(this, "Save successfully", Toast.LENGTH_SHORT).show();
    }
}

OutGoingCallReceiver.java

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;

public class OutGoingCallReceiver extends BroadcastReceiver {
    private static final String TAG = "OutGoingCallReceiver";

    // Called when making an external call
    @Override
    public void onReceive(Context context, Intent intent) {
        //  Get the user's input ip number, which is in config.xml
        SharedPreferences sp = context.getSharedPreferences("config", Context.MODE_PRIVATE);
        String ipnumber = sp.getString("ipnumber", "");

        // Get the phone number currently dialed
        String currentNumber = getResultData();
        Log.d(TAG, "currentNumber:" + currentNumber);
        // Determine if the current number is a long distance call?
        if (currentNumber.startsWith("0")) { // Long distance begins with 0
            // Modify the dialing number
            setResultData(ipnumber + currentNumber);
        }
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <EditText
        android:id="@+id/et_ipnumber"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Please input ip number"/>
    <Button
        android:onClick="onclick"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Preservation"/>
</LinearLayout>

Running example:

 

 

Monitoring SD Card Status:

Similar to the above

Define the broadcasting receiver:

Add a SdcardStateReceiver.java

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class SdcardStateReceiver extends BroadcastReceiver {
    private static final String TAG = "SdcardStateReceiver";

    // Execute when sd card status changes
    @Override
    public void onReceive(Context context, Intent intent) {
        // Get the event type of the current broadcast
        String action = intent.getAction();
        if ("android.intent.action.MEDIA_MOUNTED".equals(action)) {
            Log.d(TAG, "======sd The card is mounted.");
        } else if ("android.intent.action.MEDIA_UNMOUNTED".equals(action)) {
            Log.d(TAG, "======sd The card is unloaded.");
        }
    }
}

Configure in the manifest file:

<receiver android:name=".SdcardStateReceiver">
            <intent-filter>
                <action android:name="android.intent.action.MEDIA_MOUNTED" />
                <action android:name="android.intent.action.MEDIA_UNMOUNTED" />
                <! - Small details, here you need to configure a data, the constraint type is file, because the data type stored in the sd card is file - >.
                <data android:scheme="file" />
            </intent-filter>
        </receiver>

 

Running example:

 

 

Short Message Monitor:

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.smsstatusmonitor">

    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android:name=".SmsListenerReceiver">
            <intent-filter>
                <!--this action Hidden-->
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

MainActivity.java

import android.Manifest;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECEIVE_SMS}, 1);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0) {
                    for (int result : grantResults) {
                        if (result != PackageManager.PERMISSION_GRANTED) {
                            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                                    Manifest.permission.RECEIVE_SMS)) {
                                showPermissionDialog(permissions);
                            } else {
                                Toast.makeText(this, "You have denied permission. Please open permission manually in settings.", Toast.LENGTH_SHORT).show();
                            }
                            return;
                        }
                    }
                }
                break;
        }
    }

    private void showPermissionDialog(final String[] permissions) {
        AlertDialog.Builder dialog = new AlertDialog.Builder(this);
        dialog.setTitle("Tips!");
        dialog.setMessage("This privilege relates to sending text messages, such as rejection which needs to be opened manually in the settings.!");
        dialog.setCancelable(false);
        dialog.setPositiveButton("To grant authorization", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                ActivityCompat.requestPermissions(MainActivity.this, permissions, 1);
            }
        });
        dialog.setNegativeButton("refuse", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        });
        dialog.show();
    }
}

SmsListenerReceiver.java

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;

public class SmsListenerReceiver extends BroadcastReceiver {
    private static final String TAG = "SmsListenerReceiver";

    // Execute when SMS arrives
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "==============onReceive: ");
        // Get the sender's number and content
        Bundle extras = intent.getExtras();
        if (extras == null) return;
        Object[] objects = (Object[]) extras.get("pdus");
        String format = intent.getStringExtra("format");// Why is it explained later in "format"
        // Get an instance of smsmessage
        SmsMessage message = null;
        for (int i = 0; i < objects.length; i++) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                message = SmsMessage.createFromPdu((byte[]) objects[i], format);
            } else {
                message = SmsMessage.createFromPdu((byte[]) objects[i]);
            }
            // Get the sending address and content of the short message
            String fromAddress = message.getOriginatingAddress();
            String messageBody = message.getMessageBody().toString();
            Log.d(TAG, "=========body:" + messageBody + "-----" + fromAddress);
        }
    }
}

 

Running result example:

Can read the number and content of the received short message

 

String format = intent. getString Extra ("format") just appeared in the code; why is it "format"?

Now we see the public static SmsMessage createFromPdu(byte[] pdu, String format) method

See that this format is the code for the class android.provider.Telephony.Sms.Intents. Click in to see it.

ctrl+F lookup, see Intent class there is such a paragraph, the source code is written "format", you can take out the key, then we can imitate the execution will not be wrong.

 

 

 

Say a little more off-topic==========================

You can consult more android system source code (this onReceive method can imitate the system source code to write)

https://www.androidos.net.cn/android/8.0.0_r4/xref/packages/apps/BasicSmsReceiver/AndroidManifest.xml

Find the SmsMessageReceiver class. Here's the onReceive() method. Just copy it.

 

 

Unloading and installation of applications:

It's much the same as above.

1. Define the Broadcast Receiver

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class AppStateReceiver extends BroadcastReceiver {
    private static final String TAG = "AppStateReceiver";

    // Called when a new application is installed or an application is uninstalled
    @Override
    public void onReceive(Context context, Intent intent) {
        // Get the current broadcast event type
        String action = intent.getAction();

        if ("android.intent.action.PACKAGE_INSTALL".equals(action)) {
            Log.d(TAG, "===============The application was installed 11111111111111");
        } else if ("android.intent.action.PACKAGE_ADDED".equals(action)) {
            Log.d(TAG, "===============Application installed 222222222222222");
        } else if ("android.intent.action.PACKAGE_REMOVED".equals(action)) {
            Log.d(TAG, "===============The application is uninstalled" + intent.getData());
        }
    }
}

Annotation:

Here intent.getData() can get the name of the uninstalled application package and add or leave it as needed.

 

2. Configure in the manifest file

Inside the application tag

        <receiver android:name=".AppStateReceiver">
            <intent-filter>
                <action android:name="android.intent.action.PACKAGE_INSTALL" />
                <action android:name="android.intent.action.PACKAGE_ADDED" />
                <action android:name="android.intent.action.PACKAGE_REMOVED" />
                <!--Want to let action Events take effect, and you need to configure one data-->
                <data android:scheme="package" />
            </intent-filter>
        </receiver>

When other applications are uninstalled, the results of log printing are as follows:

When other applications are installed, the results of log printing are as follows:

 

Actually, android.intent.action.PACKAGE_INSTALL is the reserved broadcast event type.

android.intent.action.PACKAGE_ADDED is the broadcast type initiated after the application is installed.

 

=============================Talk is cheap, show me the code============================

Tags: Android xml Java encoding

Posted on Thu, 20 Dec 2018 05:54:05 -0800 by moiseszaragoza