Table of Contents
Table of Contents
1.MainActivity
2.MainActivity2
3.MyHelper
4.OutCallReceiver
5.activity_main.xml
6.activity_main2.xml
7.item.xml
8.themes.xml
9. Project code layout
10. Operation status display
11. Common errors reported in this project and their solutions
Complete an app that intercepts dialing, including the following functions:
- Main functions: Save the number set by the user and intercept dialing to the number.
- Database: Save intercepted information, number, time or number of times, etc.
- Broadcast receiver: Perform dialing interception based on the saved number, save the interception information to the database, and jump to interface 2.
- Contains two interfaces:
Interface 1 (main interface) content: save interception numbers and display historical interception information;
Interface 2 content: Prompts the user that the dial-up has been intercepted, and the interface theme is set to a dialog-type theme.
Tip: Permissions required
Dynamic permission application:
public final void requestPermissions(
String[] permissions,
int requestCode)
When jumping to Activity2, you need to set intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1.MainActivity
import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.health.PackageHealthStats; import android.view.Display; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import java.util.List; import java.util.Map; public class MainActivity extends AppCompatActivity { private EditText et_ipnumber; private SharedPreferences sp; private RecyclerView rv; private TextView update; private MyAdapter myAdapter; private List<Map<String, String>> datas; private OutCallReceiver receiver; private static final int FlatRequestCode = 1002; private final String[] permissions = {"android.permission.READ_PHONE_STATE","android.permission.PROCESS_OUTGOING_CALLS","android.permission.SYSTEM_ALERT_WINDOW","android.permission.SYSTEM_OVERLAY_WINDOW"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (!checkPermission()) { requestPermissions(permissions, 1); } MyHelper myHelper = new MyHelper(this); datas = myHelper.getAll(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("android.intent.action.NEW_OUTGOING_CALLS"); intentFilter.addAction("android.intent.action.READ_PHONE_STATE"); receiver = new OutCallReceiver(); registerReceiver(receiver, intentFilter); rv = findViewById(R.id.rv); myAdapter = new MyAdapter(); rv.setAdapter(myAdapter); rv.setLayoutManager(new LinearLayoutManager(this)); Button button = findViewById(R.id.btn_intercept); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { et_ipnumber = findViewById(R.id.et_ipnumber); String number = et_ipnumber.getText().toString().trim(); sp = getSharedPreferences("itercept", MODE_PRIVATE); SharedPreferences.Editor editor = sp.edit(); editor.putString("number", number); editor.commit(); Toast.makeText(MainActivity.this, "Save successfully", Toast.LENGTH_SHORT).show(); } }); update = findViewById(R.id.tv_update); update.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { datas = myHelper.getAll(); myAdapter.notifyDataSetChanged(); } }); } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(receiver); } private boolean checkPermission() { for (String p:permissions) { if (checkSelfPermission(p) != PackageManager.PERMISSION_GRANTED) { return false; } } return true; } class MyAdapter extends RecyclerView.Adapter<MyHolder> { @NonNull @Override public MyHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.item, parent, false); MyHolder holder = new MyHolder(view); return holder; } @Override public void onBindViewHolder(@NonNull MyHolder holder, int position) { String number = (String) datas.get(position).get("number"); String time = (String) datas.get(position).get("time"); holder.tv_number.setText(number); holder.tv_time.setText(time); } @Override public int getItemCount() { return datas.size(); } } class MyHolder extends RecyclerView.ViewHolder { TextView tv_number; TextView tv_time; public MyHolder(@NonNull View itemView) { super(itemView); tv_number = itemView.findViewById(R.id.tv_number); tv_time = itemView.findViewById(R.id.tv_time); } } }
2.MainActivity2
import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; public class MainActivity2 extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); } }
3.MyHelper
import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import androidx.appcompat.widget.ActionBarContextView; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; public class MyHelper extends SQLiteOpenHelper { private static final int version = 1; private static final String db_name = "intercept.db"; MyHelper(Context context) { super(context, db_name, null, 1); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE call(_id INTEGER PRIMARY KEY AUTOINCREMENT, number VARCHAR(20), time VARCHAR(20))"); } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) { } public void insert(String number) { Calendar calendar = Calendar.getInstance(); Date date = calendar.getTime(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String formattedDate = dateFormat.format(date); SQLiteDatabase db = getWritableDatabase(); ContentValues value = new ContentValues(); value.put("number", number); value.put("time", formattedDate); db.insert("call", null, value); db.close(); } public void delete(String number) { SQLiteDatabase db = getWritableDatabase(); db.delete("call", "number=?", new String[]{number + ""}); db.close(); } public List<Map<String, String>> getAll() { List<Map<String, String>> result = new ArrayList<>(); SQLiteDatabase db = getReadableDatabase(); Cursor cursor = db.query("call", null, null, null, null, null, null); if (cursor.getCount() != 0) { while (cursor.moveToNext()) { Map<String, String> map = new HashMap<>(); String number = cursor.getString(1); String time = cursor.getString(2); map.put("number", number); map.put("time", time); result.add(map); } } cursor.close(); db.close(); return result; } }
4.OutCallReceiver
import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; public class OutCallReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // TODO: This method is called when the BroadcastReceiver is receiving // an Intent broadcast. SharedPreferences sp = context.getSharedPreferences("itercept", context.MODE_PRIVATE); String number = sp.getString("number", ""); String outcallnumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER); if (outcallnumber.equals(number)) { setResultData(null); MyHelper myHelper = new MyHelper(context); myHelper.insert(number); } Intent intent1 = new Intent(); intent1.setClass(context, MainActivity2.class); intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent1); } }
5.activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FFFFF0" android:padding="15dp" tools:context=".MainActivity" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="10dp"> <EditText android:id="@ + id/et_ipnumber" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:hint="Please enter the blocking number"/> <Button android:id="@ + id/btn_intercept" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#ACD6FF" android:text="Save interception number" android:textSize="16sp"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:background="#ACD6FF"> <TextView android:id="@ + id/tv_update" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingTop="5dp" android:paddingRight="8dp" android:paddingBottom="2dp" android:text="Historical interception information" android:textColor="#330000" android:textSize="18sp" android:layout_gravity="center"/> <androidx.recyclerview.widget.RecyclerView android:id="@ + id/rv" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout> </LinearLayout>
6.activity_main2.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FFFFF0" tools:context=".MainActivity2"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="15dp" android:text="Don't make trouble, study hard, and take class seriously! Don't make phone calls!" android:textSize="26sp"/> </LinearLayout>
7.item.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="wrap_content" android:padding="5dp"> <TextView android:id="@ + id/tv_number" android:text="phone number" android:layout_width="0dp" android:layout_weight="2" android:layout_height="wrap_content"/> <TextView android:id="@ + id/tv_time" android:text="Interception time" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content"/> </LinearLayout>
8.themes.xml
<resources xmlns:tools="http://schemas.android.com/tools"> <!-- Base application theme. --> <style name="Theme.Assess" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> <!-- Primary brand color. --> <item name="colorPrimary">@color/purple_500</item> <item name="colorPrimaryVariant">@color/purple_700</item> <item name="colorOnPrimary">@color/white</item> <!-- Secondary brand color. --> <item name="colorSecondary">@color/teal_200</item> <item name="colorSecondaryVariant">@color/teal_700</item> <item name="colorOnSecondary">@color/black</item> <!-- Status bar color. --> <item name="android:statusBarColor">?attr/colorPrimaryVariant</item> <!-- Customize your theme here. --> </style> <style name="DialogActivity" parent="Theme.AppCompat.Light.Dialog"> <item name="colorPrimary">@color/purple_200</item> <item name="colorPrimaryVariant">@color/purple_500</item> <item name="colorOnPrimary">@color/black</item> <!-- Secondary brand color. --> <item name="colorSecondary">@color/teal_200</item> <item name="colorSecondaryVariant">@color/teal_700</item> <item name="colorOnSecondary">@color/black</item> <!-- Status bar color. --> <item name="android:statusBarColor">?attr/colorPrimaryVariant</item> <!-- Customize your theme here. --> </style> </resources>
8.AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-feature android:name="android.hardware.telephony" android:required="false" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" /> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Assess" tools:targetApi="31"> <activity android:name=".MainActivity2" android:exported="false" android:theme="@style/DialogActivity"/> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name=".OutCallReceiver" android:enabled="true" android:exported="true"> <intent-filter android:priority="1000"> <action android:name="android.intent.action.NEW_OUTGOING_CALL"/> </intent-filter> </receiver> </application> </manifest>
9. Project code layout
10. Operation status display
11. Common errors and solutions for this project
1. The theme in the values folder must be written well, as it is easy to make mistakes here.
2. Learn to check the error messages displayed in logcat