Mobil cihazlar üzerinde çalışacak bir APK dekompile ve yeniden derleme aracı geliştirmek, bir dizi aşama ve beceri gerektirmektedir. Bu süreçte Android NDK (Native Development Kit) ve JNI (Java Native Interface) gibi bileşenleri kullanarak, yerel kodları çağırmak gerekmektedir.
Şu aşamaların izlenmesi gerekir:
1. Proje Kurulumu
Android Studio kullanarak yeni bir proje oluşturalım.
1. Yeni Proje Oluşturma:
- Android Studio'yu açın ve "New Project" seçeneğini seçin.
- Projeye uygun bir isim verin ve minimum SDK sürümünü seçin (en az Android 5.0 Lollipop önerilir).
2. Gerekli İzinleri Ekleme
AndroidManifest.xml dosyasına gerekli izinleri ekleyin.
3. Kullanıcı Arayüzünü Oluşturma
activity_main.xml dosyasını düzenleyerek dosya seçimi ve işlem başlatma için bir kullanıcı arayüzü oluşturun.
4. Dosya Seçimi ve İşlem Başlatma
MainActivity.java veya MainActivity.kt dosyasında, dosya seçimi ve işlem başlatma işlevlerini oluştur.
5. JNI ve Native Kod Entegrasyonu
Native kodları çağırmak için JNI kullanarak gerekli işlemleri gerçekleştirin.
CMakeLists.txt:
native-lib.cpp:
6. Native Fonksiyonları Çağırma
MainActivity'de native fonksiyonları çağırarak decompile ve recompile işlemlerini gerçekleştirin.
kotlin
7. Uygulamayı Test Edin
Uygulamanızı cihazında veya emülatörde test edin. APK dosyasını seçin, decompile işlemini başlatın, gerekli değişiklikleri yapın ve yeniden derleyin.
Bu adımları izleyerek mobil cihazlarda çalışabilen bir APK dekompile ve yeniden derleme aracı geliştirebilirsiniz.
Şu aşamaların izlenmesi gerekir:
1. Proje Kurulumu
Android Studio kullanarak yeni bir proje oluşturalım.
1. Yeni Proje Oluşturma:
- Android Studio'yu açın ve "New Project" seçeneğini seçin.
- Projeye uygun bir isim verin ve minimum SDK sürümünü seçin (en az Android 5.0 Lollipop önerilir).
2. Gerekli İzinleri Ekleme
AndroidManifest.xml dosyasına gerekli izinleri ekleyin.
XML:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
3. Kullanıcı Arayüzünü Oluşturma
activity_main.xml dosyasını düzenleyerek dosya seçimi ve işlem başlatma için bir kullanıcı arayüzü oluşturun.
XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/selectApkButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Select APK" />
<TextView
android:id="@+id/selectedFilePath"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="No file selected" />
<Button
android:id="@+id/decompileButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Decompile APK" />
<Button
android:id="@+id/recompileButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Recompile APK" />
</LinearLayout>
4. Dosya Seçimi ve İşlem Başlatma
MainActivity.java veya MainActivity.kt dosyasında, dosya seçimi ve işlem başlatma işlevlerini oluştur.
Kod:
Kotlin
package com.example.apktool
import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.provider.OpenableColumns
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import java.io.File
import java.io.InputStream
import java.io.OutputStream
class MainActivity : AppCompatActivity() {
private val PICK_APK_FILE = 1
private lateinit var selectedFilePath: TextView
private lateinit var apkFile: File
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val selectApkButton: Button = findViewById(R.id.selectApkButton)
selectedFilePath = findViewById(R.id.selectedFilePath)
val decompileButton: Button = findViewById(R.id.decompileButton)
val recompileButton: Button = findViewById(R.id.recompileButton)
selectApkButton.setOnClickListener {
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "application/vnd.android.package-archive"
startActivityForResult(intent, PICK_APK_FILE)
}
decompileButton.setOnClickListener {
// Decompile işlemini başlatın
}
recompileButton.setOnClickListener {
// Recompile işlemini başlatın
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == PICK_APK_FILE && resultCode == Activity.RESULT_OK) {
val uri: Uri? = data?.data
uri?.let {
val fileName = getFileName(uri)
val inputStream: InputStream? = contentResolver.openInputStream(uri)
val file = File(cacheDir, fileName)
val outputStream: OutputStream = file.outputStream()
inputStream?.copyTo(outputStream)
inputStream?.close()
outputStream.close()
apkFile = file
selectedFilePath.text = apkFile.path
}
}
}
private fun getFileName(uri: Uri): String {
var result: String? = null
if (uri.scheme == "content") {
contentResolver.query(uri, null, null, null, null)?.use { cursor ->
if (cursor.moveToFirst()) {
result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
}
}
}
if (result == null) {
result = uri.path
val cut = result!!.lastIndexOf('/')
if (cut != -1) {
result = result!!.substring(cut + 1)
}
}
return result!!
}
}
5. JNI ve Native Kod Entegrasyonu
Native kodları çağırmak için JNI kullanarak gerekli işlemleri gerçekleştirin.
CMakeLists.txt:
Kod:
cmake
cmake_minimum_required(VERSION 3.4.1)
add_library(native-lib SHARED
src/main/cpp/native-lib.cpp)
find_library(log-lib log)
target_link_libraries(native-lib ${log-lib})
native-lib.cpp:
C++:
#include <jni.h>
#include <string>
#include <cstdlib>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_apktool_MainActivity_stringFromJNI(JNIEnv* env, jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
extern "C" JNIEXPORT void JNICALL
Java_com_example_apktool_MainActivity_decompileApk(JNIEnv *env, jobject /* this */, jstring apkPath) {
const char *path = env->GetStringUTFChars(apkPath, nullptr);
// apktool komutunu çalıştırın
std::string command = "apktool d " + std::string(path);
system(command.c_str());
env->ReleaseStringUTFChars(apkPath, path);
}
extern "C" JNIEXPORT void JNICALL
Java_com_example_apktool_MainActivity_recompileApk(JNIEnv *env, jobject /* this */, jstring directoryPath) {
const char *path = env->GetStringUTFChars(directoryPath, nullptr);
// apktool komutunu çalıştırın
std::string command = "apktool b " + std::string(path);
system(command.c_str());
env->ReleaseStringUTFChars(directoryPath, path);
}
6. Native Fonksiyonları Çağırma
MainActivity'de native fonksiyonları çağırarak decompile ve recompile işlemlerini gerçekleştirin.
kotlin
Kod:
class MainActivity : AppCompatActivity() {
// Native fonksiyonları bildir
external fun stringFromJNI(): String
external fun decompileApk(apkPath: String)
external fun recompileApk(directoryPath: String)
// Statik blokta native kütüphaneleri yükle
companion object {
init {
System.loadLibrary("native-lib")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
// onCreate fonksiyonu burada
}
private fun decompileApkFile() {
val apkPath = apkFile.path
decompileApk(apkPath)
}
private fun recompileApkFile() {
val directoryPath = apkFile.parent
recompileApk(directoryPath)
}
}
7. Uygulamayı Test Edin
Uygulamanızı cihazında veya emülatörde test edin. APK dosyasını seçin, decompile işlemini başlatın, gerekli değişiklikleri yapın ve yeniden derleyin.
Bu adımları izleyerek mobil cihazlarda çalışabilen bir APK dekompile ve yeniden derleme aracı geliştirebilirsiniz.


