Administrator
发布于 2025-03-07 / 1040 阅读

SDK安卓集成文档

Android集成

一、安卓

1.下载导入SDK

下载 ProxyLibrary-release.aar,放到项目的 libs 文件夹中,并使用 gradle 导入

implementation(files("libs\\ProxyLibrary-release.aar"))

或者导入libs目录中所有 jar 文件

implementation fileTree(dir: 'libs', include: ['*.jar'])

sdk最小支持安卓sdk26,所以您的项目中,运行在所有 API Level ≥ 26 的设备上

minSdk = 26

2.初始化

在 AndroidManifest.xml 文件中添加权限声明(网络权限和应用内部文件的读写)

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

在 AndroidManifest.xml 文件中的 application 标签内设置 com.wayl.proxy.UUID(修改,和iOS保持统一)

添加云配置:如果需要云配置,要配置com.wayl.proxy.config_cloud 目前支持GITEE TENCENT

该配置写法是json格式,需要将自己云服务的信息写入,如果放到strings.xml文件中则需要加上转义字符,如果不使用另一个类型,直接删除

{
  "GITEE": [
    "https://gitee.com/api/v5/repos/******************master"
  ],
  "TENCENT": [
    {
      "url": "https://*********sdk.json"
    }
  ],
  "ALIYUN": [
    {
      "url": "https:/***********/sdk.json"
    }
  ]
}
<!--配置可能会过长可以放到自己的strings.xml中引入-->
<meta-data
  android:name="com.wayl.proxy.config_cloud"
  android:value="@string/config_cloud"/>
  
<!--strings.xml-->
<string name="config_cloud">{\"GITEE\":[\"https://gitee.com/api/v5/repos/******************ref=master\"],\"TENCENT\":[{\"url\":\"https://*********sdk.json\"}],\"ALIYUN\":[{\"url\":\"https:/***********/sdk.json\"}]}</string>
<meta-data
    android:name="com.wayl.proxy.UUID"
    android:value="xxxxxxxxxxxxxxxxxxxxxxxxx"/>

完整 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-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <application
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.android"
        usesCleartextTraffic="true"
        tools:targetApi="31"
        tools:ignore="MissingApplicationIcon">
        
       <!--UUID-->
        <meta-data
            android:name="com.wayl.proxy.UUID"
            android:value="xxxxxxxxxxxxxxxxxxx"/>
        <!--配置可能会过长可以放到自己的strings.xml中引入-->
        <meta-data
            android:name="com.wayl.proxy.config_cloud"
            android:value="@string/config_cloud"/>

        <activity
            android:name="com.proxy.test.MainActivity"
            android:exported="true"
            android:theme="@style/Theme.android">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

调用init初始化修改,直接调用

注意:

如果app存在权限申请,确保初始化和权限申请不要同步进行(最好在权限申请完成后调用)。
/**
     * 初始化代理服务
     *
     * @param context  上下文
     */
 public static Result init(@NonNull Context context) {}
 val result = WaylProxy.init(this)

3.功能使用修改启动方法回调

启动代理,传入需要的端口号,启动成功以后将监听该本地端口的所有请求

当然也可以不传,我们默认会随机一个端口使用 {"data":{"port":8088},"message":"代理启动成功,监听端口: 8088","success":true}

/**
     * 启动代理服务
     *
     * @param context 上下文
     * @param port    端口号
     * @param callback 完成后的回调
     * @return 启动结果
     */
public static void start(@NonNull Context context, @NonNull Integer port, @NonNull Consumer<Result> callback) {}

/**
    * 启动代理服务 (无端口)
    *
    * @param context 上下文
    * @param callback 完成后的回调
    * @return 启动结果
    */
public static void start(@NonNull Context context, @NonNull Consumer<Result> callback) {}

WaylProxy.start(this, port) { result: Result ->
   Log.i(TAG, result.toString())
   //成功打印数据  {"data":{"port":8080},"message":"代理启动成功,监听端口: 12345","success":true}
}

WaylProxy.start(this) { result: Result ->
   Log.i(TAG, result.toString())
   //成功打印数据  {"data":{"port":12345},"message":"代理启动成功,监听端口: 12345","success":true}
}

//获取当前版本
String version = WaylProxy.getVersion()

也可以调用该方法先拿到一个空闲端{"data":{"port":12348},"message":"完成","success":true}

Result result = WaylProxy.getFreePort();
//成功打印数据  {"data":{"port":12348},"message":"完成","success":true}

停止代理服务

WaylProxy.stop()

清除代理服务,该方法会清除掉所有的代理数据,清理以后,是无法再次调用启动方法,需要初始化重新开启

WaylProxy.clear()

获取代理状态,一共有三个值,

初始化是否成功

启动是否成功

验证套餐是否成功

// 初始化状态 true fasle
Boolean initStatus = WaylProxy.initStatus();
// 启动状态   true fasle
Boolean startStatus = WaylProxy.startStatus();
// 验证状态   true fasle
Boolean validationStatus = WaylProxy.validationStatus();

Log.i(TAG, "initStatus:" + initStatus);
Log.i(TAG, "validationStatus:" + validationStatus);
Log.i(TAG, "startStatus:" + startStatus);

//设置监听
WaylProxy.addStateChangeListener(new ProxyStateChangeListener() {
    @Override
    public void onInitStatusChanged(boolean newStatus) {
        Log.i("WaylProxyListener", "初始化状态: " + newStatus);
    }
    @Override
    public void onValidationStatusChanged(boolean newStatus) {
        Log.i("WaylProxyListener", "验证状态: " + newStatus);
    }
    @Override
    public void onStartStatusChanged(boolean newStatus) {
        Log.i("WaylProxyListener", "验证状态: " + newStatus);
    }
});

4.举例:

启动成功以后,sdk会监听本地端口的所有请求。

然后您将请求转入到本地的代理端口,类型全部是socks,http也可以。

socks 代理,如:socks://127.0.0.1:8080

http 代理,如:http://127.0.0.1:8080

如需要使用其他依赖,请查看其他第三方依赖如何设置请求代理,这里不一 一举例了

(建议需要代理的所有请求不要使用缓存)

okhttp设置代理 java:

// socks://127.0.0.1:8080
SocketAddress socketAddress = new InetSocketAddress("127.0.0.1", 8080);

Proxy proxy = new Proxy(Proxy.Type.SOCKS, socketAddress);

OkHttpClient client = new OkHttpClient.Builder()
        .pingInterval(20, TimeUnit.SECONDS)
        .connectTimeout(10, TimeUnit.SECONDS)
        .writeTimeout(10, TimeUnit.SECONDS)
        .readTimeout(10, TimeUnit.SECONDS)
        .connectionPool(new ConnectionPool(0, 1, TimeUnit.MILLISECONDS)) //禁用连接池
        .cache(null)
        .proxy(proxy)
        .build();

整体使用案例kotlin:

package com.wayl.proxy.test

import android.annotation.SuppressLint
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.logging.HttpLoggingInterceptor
import java.net.InetSocketAddress
import java.net.Proxy
import java.util.concurrent.TimeUnit

object OkHttpRequestClient {

    private val client: OkHttpClient

    fun getClient(): OkHttpClient = client

    init {
         // 设置代理
        val proxyAddress = InetSocketAddress("127.0.0.1", 8080)
        val proxy = Proxy(Proxy.Type.SOCKS, proxyAddress)

        val logging = HttpLoggingInterceptor().apply {
            HttpLoggingInterceptor.Level.BODY.also { this.level = it }
        }

        val headerInterceptor = Interceptor { chain ->
            val originalRequest = chain.request()
            val requestBuilder = originalRequest.newBuilder()
                .header("Content-Type", "application/json")

            val modifiedRequest = requestBuilder.build()
            chain.proceed(modifiedRequest)
        }

        client = OkHttpClient.Builder()
             .pingInterval(20, TimeUnit.SECONDS)
            .connectTimeout(10, TimeUnit.SECONDS)
            .writeTimeout(10, TimeUnit.SECONDS)
            .readTimeout(10, TimeUnit.SECONDS)
            .hostnameVerifier { _, _ -> true }
            .addInterceptor(logging)
            .connectionPool(ConnectionPool(0, 5, TimeUnit.SECONDS))
            .cache(null)
            .proxy(proxy)
            .addInterceptor(headerInterceptor)
            .build()
    }
}
package com.wayl.proxy.test

import android.annotation.SuppressLint
import android.os.Bundle
import android.util.Log
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import androidx.drawerlayout.widget.DrawerLayout
import androidx.lifecycle.lifecycleScope
import com.wayl.proxy.library.WaylProxy
import com.wayl.proxy.library.listener.ProxyStateChangeListener
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.Call
import okhttp3.Callback
import okhttp3.Request
import okhttp3.Response
import java.io.IOException


class MainActivity : AppCompatActivity() {
    companion object {
        private const val TAG = "MainActivity"
    }

    private lateinit var drawerLayout: DrawerLayout

    private val port: Int = 8080
    private val requestURL: String = "https://google.com"

    @SuppressLint("MissingInflatedId")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        drawerLayout = findViewById(R.id.drawer_layout)
        val close: Button = findViewById(R.id.close_btn)
        val open: Button = findViewById(R.id.open_btn)
        val clear: Button = findViewById(R.id.clear_btn)
        val request: Button = findViewById(R.id.request_btn)
        val init: Button = findViewById(R.id.init_btn)

        WaylProxy.addStateChangeListener(object : ProxyStateChangeListener {
            override fun onInitStatusChanged(newStatus: Boolean) {
                Log.i(TAG, "初始化状态: $newStatus")
            }

            override fun onValidationStatusChanged(newStatus: Boolean) {
                Log.i(TAG, "验证状态: $newStatus")
            }

            override fun onStartStatusChanged(newStatus: Boolean) {
                Log.i(TAG, "启动状态: $newStatus")
            }
        })


        init.setOnClickListener {
            val result = WaylProxy.init(this)
            Log.i(TAG, result.toString())
        }

        request.setOnClickListener {
            lifecycleScope.launch(Dispatchers.IO) {
                val request = Request.Builder()
                    .url(requestURL)
                    .get().build()

                OkHttpRequestClient.getClient().newCall(request).enqueue(object : Callback {
                    override fun onFailure(call: Call, e: IOException) {
                        Log.e(TAG, "请求失败", e)
                    }

                    override fun onResponse(call: Call, response: Response) {
                        if (response.isSuccessful) {
                            Log.i(TAG, "请求成功")
                        } else {
                            Log.e(TAG, "请求失败")
                        }
                    }
                })
            }
        }

        clear.setOnClickListener {
            WaylProxy.clear()
        }

        close.setOnClickListener {
            WaylProxy.stop()
        }

        open.setOnClickListener {
            lifecycleScope.launch(Dispatchers.IO) {
            WaylProxy.start(this, port) { result: Result ->
                Log.i(TAG, result.toString())
            }
        }
        Log.i(TAG, WaylProxy.getFreePort().toString())
        val result = WaylProxy.init(this)
        Log.i(TAG, result.toString())
    }
}