Android 第三方應用市場如何繞過手機廠商對apk的檢測

要繞過手機廠商對於安裝apk的檢測無非就是在apk下載完成安裝時切斷用戶的網絡(這個期間一般也就10s左右的時間安裝apk完成的時間也和這個差多不這個視手機而定),so 要實現這樣的效果,首先想到的是切斷用戶的手機網絡,但實際的開發中這樣做還是有一大堆的問題。之後偶然的發現了通過vpn的這種方式來實現。可以解決這樣的問題只是用戶在第一次安裝的時候讓用戶選擇開啓VPN就哦了。如果看到的童鞋有更好的想法歡迎拍磚。
要使用vpn的話用到的是VpnService 這個類是在android.net.VpnService 包底下如圖
官網鏈接
這裏寫圖片描述

OK代碼如下:
1.創建一個MyVpnService


import android.content.Intent;
import android.net.VpnService;
import android.os.ParcelFileDescriptor;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.InetSocketAddress;
import java.nio.channels.DatagramChannel;

/**
 * Created by vc on 2017/6/28.
 */

public class MyVpnService extends VpnService {


    private Thread mThread;

    private ParcelFileDescriptor  mParcelFileDescriptor;


    private Builder  mBuilder =new Builder(); // VpnService.Builder





    @Override
    public int onStartCommand(Intent intent,int flags, int startId) {

        final boolean  flag = intent.getBooleanExtra("showtime",true);

        mThread =new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    mParcelFileDescriptor = mBuilder.setSession("myVpnService") // 給session設置一個名稱

                                            .addAddress("192.168.0.1",24)//給vpn的接口添加一個地址

                                            .addDnsServer("8.8.8.8") //添加一個dns的服務給vpn

                                            .addRoute("0.0.0.0",0)//將網絡路由器器添加到vpn的接口

                                            .establish() ;  //表示使用此構建器的參數創建vpn的接口


                    FileInputStream inputStream = new FileInputStream(mParcelFileDescriptor.getFileDescriptor());  // 發送數據包排隊在這個輸入流上

                    FileOutputStream out = new FileOutputStream( mParcelFileDescriptor.getFileDescriptor());  //接收到的數據包寫入輸出流


                    //DatagramChannel 是一個能收發UDP包的通道。因爲UDP是無連接的網絡協議,所以不能像其它通道那樣讀取和寫入。它發送和接收的是數據包。

                    DatagramChannel datagramChannel =DatagramChannel.open();

                    datagramChannel.connect(new InetSocketAddress("127.0.0.1",8087));

                    protect(datagramChannel.socket());  // 保護socket 與vpn鏈接

                    /*if(flag){
                        while (true) {  //循環傳輸數據包

                            Thread.sleep(100);
                        }
                    }else {

                        Thread.sleep(10000);
                    }*/

                Thread.sleep(10000); // 這裏定義了一個時間



                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                     try {
                      if(mParcelFileDescriptor!=null){
                          mParcelFileDescriptor.close();
                          mParcelFileDescriptor=null;
                      }


                    }catch (Exception e ){
                        e.printStackTrace();
                    }

                }


            }
        });

        mThread.start();

        return START_NOT_STICKY;
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
         if(mThread!=null){
             mThread.interrupt();
         }

    }
}

2,在Androidmanifest.xml 註冊當前的MyVpnService

 <service
            android:name=".MyVpnService"
            android:permission="android.permission.BIND_VPN_SERVICE">
            <intent-filter>
                <action android:name="android.net.VpnService"/>
            </intent-filter>
        </service>

3.到此主要的vpnservice 已經完成了。接下來是打開vpnservice,主要代碼如下:

 Intent intent = VpnService.prepare(InstallActivity.this);//準備vpnservice的連接

        if(intent!=null){

            startActivityForResult(intent,0);
        }else {

            onActivityResult(0,RESULT_OK,null);
        }

處理結果需要在onActivityResult中

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

       Log.e(TAG,"onActivityResult");
        if(resultCode== RESULT_OK){
            Intent intent = new Intent(this,MyVpnService.class);
            startService(intent);

        }

    }

這樣就可以開啓一個vpn的service了。走到這裏你可能覺得這不就是一個開啓vpnservice麼,別忘了我們要做的是安裝apk的時候繞過廠商特殊機型的對apk的檢測,有一種解決思路就是每次安裝apk的時候都走一個installActivity 這個activity是透明的切只有一個像素的大小


import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.net.Uri;
import android.net.VpnService;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.util.Log;
import android.view.WindowManager;

import java.io.File;


// 安裝app的activity
public class InstallActivity extends Activity {

    private boolean isShow= true;  // 用於判斷當前activity的顯示狀態

    private MyVpnService mMyVpnService;

   private final  String TAG="InstallActivity";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e(TAG,"onCreate");

        //設置activity的大小
        WindowManager.LayoutParams  params = getWindow().getAttributes();
        params.width = 1;
        params.height = 1;
        params.dimAmount= 0.0f;
        getWindow().setAttributes(params);

         Intent intent = VpnService.prepare(InstallActivity.this);

        if(intent!=null){

            startActivityForResult(intent,0);
        }else {

            onActivityResult(0,RESULT_OK,null);
        }



    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.e(TAG,"onResume");
        if(!isShow){
             Log.e(TAG,"onResume finish ");
            finish();
         }


    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    @Override
    protected void onPause() {
        super.onPause();
        isShow =false;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.e(TAG,"onDestroy");

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

       Log.e(TAG,"onActivityResult");
        if(resultCode== RESULT_OK){
            isShow =false;
            Intent intent = new Intent(this,MyVpnService.class);
            startService(intent);

//處理完成後安裝apk這裏寫個一個本地路徑實際開發中需要傳入安裝apk的路徑
          inStallApp(Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+"q.apk");

        }

    }




    private void inStallApp(String path){

        Uri uri = Uri.fromFile(new File(path));

        Intent intent = new Intent(Intent.ACTION_VIEW);

        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        intent.setDataAndType(uri,"application/vnd.android.package-archive");

       startActivity(intent);

    }


}

設置activity透明的主題

 <style name="transparent_theme" parent="@android:style/Theme.Translucent.NoTitleBar"></style>

需要注意的就是installactivity需求繼承activity否則這麼幹會報錯的。這裏只能算是一種解決思路實際中對於不同的廠商哪些是對apk安裝檢測的還需要去統計不同的機型。如果有更好的想法歡迎拍磚

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章