Realization of Mobile Security Guard Based on android

Next, we implement the communication guard function, which is to provide users with a blacklist function. Users add the number they don't want to answer to the blacklist and hang up automatically if the number calls.

Because the view is separated, we design the interface first. Blacklist management interface is relatively simple, with only one title, a "Add" button, and then a ListView to display all blacklists. If the blacklist is empty, the "no blacklist" is displayed. Long press blacklist number will pop up menu options, delete or modify. blacklist_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/blacklist"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:layout_marginBottom="5dp"
            android:textSize="30dp"
            android:text="Blacklist management"/>
        <Button
            android:id="@+id/add"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="5dp"
            android:layout_marginLeft="260dp"
            android:text="Add to"/>
    </RelativeLayout>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <ListView
            android:id="@+id/blacknum_list"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">
        </ListView>
        <TextView
            android:id="@+id/tips"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:text="Blacklist is empty"/>
    </LinearLayout>
</LinearLayout>

This listview is simple, just showing a string black_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
<TextView
    android:id="@+id/number"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="strings"/>
</LinearLayout>

Clicking on the Add or Modify button pops up a dialog box to enter the number. black_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
<EditText
    android:id="@+id/add_number_Dialog"
    android:hint="Please enter the number."
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>
    <LinearLayout android:layout_height="wrap_content"
        android:layout_width="match_parent">
    <Button
        android:id="@+id/ok_number_Dialog"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Sure?"
        android:layout_marginLeft="1dp"/>
        <Button
            android:id="@+id/cancel_number_Dialog"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="cancel"
            android:layout_marginLeft="120dp"/>
    </LinearLayout>
</LinearLayout>

Next, write the main logic for blacklisting:

First of all, to achieve blacklist function, a major prerequisite is to establish a database, android provides a lightweight sqlite database, which is a text file.

Let's first build a blacknumDBHelper class, which inherits from SQLiteOpenHelper

package com.yangmiaoqing.example.myassitant;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * Created by yangmiaoqing on 2018/3/29.
 */

public class blacknumDBHelper extends SQLiteOpenHelper {
    private static SQLiteOpenHelper mInstance;
    private final static String name="blacknumber.db";
    public static SQLiteOpenHelper getInstance(Context context){
        if (mInstance==null){
            mInstance=new blacknumDBHelper(context,name,null,1);
        }
        return mInstance;
    }
    public blacknumDBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory,int version){
        super(context,name,factory,version);
    }
    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL("create table blacknumber(_id integer primary key autoincrement,number text)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}

First, we get an instance of SQLiteOpenHelper. Publishing number and database name are written in super. Then we build a blacklist table in onCreate. There are only two fields in the table, namely serial number and number. onUpgrade is used when the database is updated.

Then the database operation class blacknumberDao

package com.yangmiaoqing.example.myassitant;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by yangmiaoqing on 2018/3/29.
 */

public class blacknumberDao {
    private SQLiteOpenHelper mInstance;
    public blacknumberDao(Context context){
        mInstance=blacknumDBHelper.getInstance(context);
    }
    public void add(String number){
        SQLiteDatabase db=mInstance.getWritableDatabase();
        if(db.isOpen()){
            ContentValues values=new ContentValues();
            values.put("number",number);
            db.insert("blacknumber",null,values);
            db.close();
            Log.e("TAG","Add success");
        }
    }
    public boolean isBlackNumber(String number){
        boolean isExist=false;
        SQLiteDatabase db=mInstance.getReadableDatabase();
        if(db.isOpen()){
            Cursor c=db.query("blacknumber",null,"number =?",new String[]{number},null,null,null);
            if(c.moveToFirst()){
                isExist=true;
            }
            c.close();
            db.close();
        }
        return isExist;
    }
    public void delete(String number){
        SQLiteDatabase db=mInstance.getWritableDatabase();
        if(db.isOpen()){
            db.delete("blacknumber","number=?",new String[]{number});
            db.close();
        }
    }
    public List<String> findAll(){
        List<String>blacknumbers=new ArrayList<String>();
        SQLiteDatabase db=mInstance.getReadableDatabase();
        if(db.isOpen()){
            Cursor c=db.query("blacknumber",new String[]{"number"},null,null,null,null,null);
            while (c.moveToNext()){
                String number=c.getString(0);
                blacknumbers.add(number);
            }
            c.close();
            db.close();
        }
        return blacknumbers;
    }
    public int queryId(String number){
        int _id=0;
        SQLiteDatabase db=mInstance.getReadableDatabase();
        if(db.isOpen()){
            Cursor c=db.query("blacknumber",new String[]{"_id"},"number=?",new String[]{number},null,null,null);
            if(c.moveToFirst()){
                _id=c.getInt(0);
            }
            c.close();
            db.close();
        }
        return _id;
    }
    public void update(int id,String number){
        SQLiteDatabase db=mInstance.getWritableDatabase();
        if(db.isOpen()){
            ContentValues values=new ContentValues();
            values.put("number",number);
            db.update("blacknumber",values,"_id=?",new String[]{id+""});
            db.close();
        }
    }
}

The main database operations needed are insertion, query whether it is a blacklist, delete, modify, and find out all the blacklist numbers returned in the form of a List.

All blacklists need to be displayed. As we said earlier, the content is contained in a ListView. Receive this LIstView adapter first. Blacknum Adapter inherits from BaseAdapter this time. Because it's relatively simple, you just need to rewrite getView.

package com.yangmiaoqing.example.myassitant;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.List;

/**
 * Created by yangmiaoqing on 2018/3/29.
 */

public class blacknumberAdapter extends BaseAdapter {
    private List<String> list=null;
    private Context context=null;
    private LayoutInflater inflater=null;
    public blacknumberAdapter(Context context,List<String> list){
        this.context=context;
        this.list=list;
        inflater=LayoutInflater.from(context);
    }
    public void setBlackNumbers(List<String> list){
       this.list=list;
    }
    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Object getItem(int i) {
        return list.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        String s=list.get(i);
        view=inflater.inflate(R.layout.black_item,null);
        TextView textView=(TextView)view.findViewById(R.id.number);
        textView.setText(s);
        return view;

    }
}

Next comes the blacklist operation logic blacknumber_activity.java

package com.yangmiaoqing.example.myassitant;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.List;

/**
 * Created by yangmiaoqing on 2018/3/29.
 */

public class blacklist_Activity extends Activity implements View.OnClickListener {
    private  static final int MENU_UPDATE_ID=0;
    private static final int MENU_DELETE_ID=1;
    private TextView tips;
    private Button add_blacknum;
    private ListView list_blacknumber;
    private LayoutInflater mInflater;
    private EditText add_number_Dialog;
    private Button ok_number_Dialog;
    private Button cancle_number_Dialog;
    private AlertDialog dialog;
    private String blacknumber;
    private View view;
    private blacknumberDao blacknumberDao;
    private blacknumberAdapter blacknumberAdapter;
    private int flag = 0;
    private final static int ADD = 1;
    private final static int UPDATE = 2;

    @Override
    protected void onCreate(Bundle savedInstance){
        super.onCreate(savedInstance);
       // blacknumber=getIntent().getStringExtra("number");
        setContentView(R.layout.blacklist_layout);



        add_blacknum=(Button)findViewById(R.id.add);
        list_blacknumber=(ListView)findViewById(R.id.blacknum_list);
        tips=(TextView)findViewById(R.id.tips);
        mInflater=(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view=mInflater.inflate(R.layout.black_menu,null);  //To load context menu layout
        add_number_Dialog=(EditText)view.findViewById(R.id.add_number_Dialog);
        ok_number_Dialog=(Button)view.findViewById(R.id.ok_number_Dialog);
        cancle_number_Dialog=(Button)view.findViewById(R.id.cancel_number_Dialog);
        ok_number_Dialog.setOnClickListener(this);
        cancle_number_Dialog.setOnClickListener(this);

        list_blacknumber.setEmptyView(tips);    //Display information when listview is empty
        blacknumberDao=new blacknumberDao(this);
        List<String>blacknumbers=blacknumberDao.findAll();
        blacknumberAdapter=new blacknumberAdapter(this,blacknumbers);
        list_blacknumber.setAdapter(blacknumberAdapter);
        add_blacknum.setOnClickListener(this);

        registerForContextMenu(list_blacknumber);     //Register the context menu for listview

       
    }


    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo){
        super.onCreateContextMenu(menu,v,menuInfo);
        menu.add(0,MENU_UPDATE_ID,0,"To update");                  //Meaning of four parameters: 1, grouping 2, ID 3, display order 4, display information
        menu.add(0,MENU_DELETE_ID,0,"delete");
    }
    @Override
    public boolean onContextItemSelected(MenuItem item){
        AdapterView.AdapterContextMenuInfo acmi=(AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
        int position=acmi.position;
        blacknumber=(String)blacknumberAdapter.getItem(position);
        int id=item.getItemId();
        switch(id){
            case MENU_UPDATE_ID:
                ViewGroup parent=(ViewGroup)view.getParent();
                if(parent!=null)parent.removeAllViews();         
               // add_number_Dialog.setText(blacknumber);
                AlertDialog.Builder builder=new AlertDialog.Builder(this);
                builder.setTitle("Update the blacklist");
                builder.setView(view);
                dialog=builder.create();
                dialog.show();
                flag=UPDATE;
                break;
            case MENU_DELETE_ID:
                blacknumberDao.delete(blacknumber);
                blacknumberAdapter.setBlackNumbers(blacknumberDao.findAll());
                blacknumberAdapter.notifyDataSetChanged();
                break;
            default:
                break;
        }
        return super.onContextItemSelected(item);
        }

    public void onClick(View v){
        int id=v.getId();
        switch (id){
            case R.id.add:
                ViewGroup parent = (ViewGroup) view.getParent();
                if(parent != null){
                    parent.removeAllViews();
                }
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                add_number_Dialog.setText("");
                builder.setTitle("Add blacklist");
                builder.setView(view);
                dialog = builder.create();
                dialog.show();
                flag = ADD;
                break;
            case R.id.ok_number_Dialog:
                String number=add_number_Dialog.getText().toString();
                if("".equals(number))
                    Toast.makeText(this,"Blacklist number cannot be empty",Toast.LENGTH_LONG).show();
                else{
                    boolean isBlackNumber=blacknumberDao.isBlackNumber(number);
                    if(isBlackNumber)Toast.makeText(this,"This number already exists",Toast.LENGTH_LONG).show();
                    else {
                        if(flag==ADD){
                            blacknumberDao.add(number);
                            Toast.makeText(this,"Add success",Toast.LENGTH_LONG).show();
                        }else if(flag==UPDATE){
                           int _id=blacknumberDao.queryId(blacknumber);
                            String number1=add_number_Dialog.getText().toString();
                            blacknumberDao.update(_id,number1);
                            Toast.makeText(this,"Modified success",Toast.LENGTH_LONG).show();
                        }
                        dialog.dismiss();
                        List<String> blacknumbers=blacknumberDao.findAll();
                        blacknumberAdapter.setBlackNumbers(blacknumbers);
                        blacknumberAdapter.notifyDataSetChanged();
                    }
                }
                break;
            case R.id.cancel_number_Dialog:
                dialog.dismiss();
                break;
        }
    }

    @Override
    public void onPointerCaptureChanged(boolean hasCapture) {

    }
}

These are all local blacklist operations, followed by the most important: to monitor calls, determine whether there is a blacklist, if there is, call endcall, automatically hang up the phone.

It is worth mentioning that android does not disclose this method, that is to say, it does not directly provide us with the use, but it does exist. How to use it? reflex

 

What we need to add here is that since we are intercepting calls directly, which is equivalent to cross-process communication, aidl will be on the scene at this time, thanks to Android's interface:
Because the following code calls these interfaces, we are ready to submit:

1. Create a new package of android.telephony in the root directory and a new aidl file named Neighboring CellInfo.

2. Create a new package of com.android.internal.telephony in the root directory, and create an aidl file named ITelephony in it.

This must be done well, otherwise the method cannot be invoked.

package com.yangmiaoqing.example.myassitant;

import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;


import com.android.internal.telephony.ITelephony;

import java.lang.reflect.Method;

/**
 * Created by yangmiaoqing on 2018/3/30.
 */

public class blackNumService extends Service {
  private boolean isblacknum;
  private blacknumberDao blacknumber=new blacknumberDao(this);
  private TelephonyManager tm;
  private MyPhoneStateListener listener;
  private NotificationManager nm;
@Override
public void onCreate(){
  super.onCreate();
  tm= (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
  listener=new MyPhoneStateListener();
  tm.listen(listener,PhoneStateListener.LISTEN_CALL_STATE);
}


  private final class MyPhoneStateListener extends PhoneStateListener{
    @Override
    public void onCallStateChanged(int state,String incomingnumber){
        super.onCallStateChanged(state,incomingnumber);
        //isblacknum=true;
        switch (state){
          case TelephonyManager.CALL_STATE_RINGING:
            isblacknum=blacknumber.isBlackNumber(incomingnumber);
            Log.e("blackNumService",incomingnumber+"Incoming call");
            if(isblacknum){
              endCall();
            }
            break;
          case TelephonyManager.CALL_STATE_IDLE:
            break;
          case TelephonyManager.CALL_STATE_OFFHOOK:
            break;
          default:
            break;
        }
    }
  }

  private void endCall(){
    try {
      Class<?> clazz = Class.forName("android.os.ServiceManager");
      Method method = clazz.getMethod("getService", String.class);
      IBinder ibinder = (IBinder) method.invoke(null, Context.TELEPHONY_SERVICE);
      ITelephony iTelephony = ITelephony.Stub.asInterface(ibinder);
      iTelephony.endCall();

    } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

Explain that this monitoring function must be in the background service, so inherit from Service, monitor the status of calls in MyPhoneStateListener, if it rings, then judge whether the caller number is in the blacklist, if it is, call endcall to hang automatically. The endcall function takes advantage of the reflection mechanism to get the method endcall that gets ITelephone through IBinder.

Finally, it should be pointed out that after Android 6.0, it is dynamic to get the right to listen on the phone. As I said earlier, this permission is actually applied for in Mainactivity. So far, even if the communication guard function is basically completed, it will be perfected after all the functions are completed.

(Subsequently) Because the switch to add blacklist function to the settings is actually very simple, but there are problems in doing so. In theory, we only need to stop our service, but it is not feasible to try for half a day, and the list function can not be stopped. Finally, we found that the service stopped not immediately, but after all the functions were completed, we PhoneStateListener was still in the listening state, just need to add in onDestroy.

tm.listen(listener,PhoneStateListener.LISTEN_NONE);

that will do

Tags: Android Database xml Java

Posted on Mon, 16 Sep 2019 04:02:49 -0700 by Acs