解决飞鸽传输2.3.6在安卓11上无法调用apk安装器的问题

查看 115|回复 11
作者:wangchz   

[color=]【修复所写代码已开源,见 https://gitee.com/kbtxwer/feige-fix/】

上回书说到:我们通过修改返回值去掉了飞哥传输的广告,但飞哥传输毕竟是很古老的软件了,在安卓11上虽然还基本能正常运行,但无法通过它直接安装收到的apk,这会给我的使用带来些许不便
原本还可以利用ES文件中转站解决,但我最近破解的旧版ES文件浏览器没这个功能,于是只好上网找找安卓11上安装软件的新方法,尝试融进飞哥传输中:
根据 Android Apk安装(兼容Android11 Api30)中的描述,安卓11废弃了 Intent.ACTION_INSTALL_PACKAGE 字段,使以前的安装方法不再可用
文中还给了示例代码,不过引入kt会让安装包体积大增,因此要转换为java的实现。
用jadx打开上回修改好的飞哥传输,定位到 com.tj.feige.app.a.e 的577行附近,发现一个静态无返回值的b(Context context, String str)方法,这就是我们要改的方法了:


image.png (86.15 KB, 下载次数: 0)
下载附件
2022-10-31 19:05 上传

可以看出它在无条件调用
[color=] android.intent.action.VIEW
而我们要让这个方法在传入的文件后缀为apk,且安卓版本不小于11(sdk 30)时,走我们新增的逻辑(代码不能在jadx里直接修改,手动改smail也不现实,所以我在这里用Android Studio重新建立简化的开发环境写代码)
[Java] 纯文本查看 复制代码
package com.tj.feige.app.a;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import com.kbtx.AppInstaller;
import java.io.File;
import java.io.IOException;
public class e {
    private static String a(File file){
        return "";
    };
    private static void a(Context context, String str){}
    @SuppressLint("WrongConstant")
    public static void b(Context context, String str){
        File file = new File(str);
        Intent intent = new Intent();
        intent.addFlags(268435456);
        if(file.getName().endsWith(".apk") && Build.VERSION.SDK_INT >= 30){
            intent.setClass(context, AppInstaller.class);
        }else {
            intent.setAction("android.intent.action.VIEW");
        }
        intent.setDataAndType(Uri.fromFile(file),a(file));
        context.startActivity(intent);
    }
}
我们在Android Studio里新建的类路径应当和飞哥传输里原有的完全一致,这样就可以直接从编译出来的dex中提取对应的smail汇编直接覆盖,如果这个方法调用了dex里的其他函数,只要建一个空壳,然后假装调用就行,确保编译过程不出错。
注意到代码里调用了 AppInstaller.class,这是我仿照文章用Java实现的安装器,代码如下:
[Java] 纯文本查看 复制代码package com.kbtx;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageInstaller;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class AppInstaller extends Activity implements View.OnClickListener {
    private static final String action = "com.kbtx.Install_APK";
    private boolean should_kill = false;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Uri uri = getIntent().getData();
        should_kill = false;
        if (uri != null && uri.getScheme().equals("file")) {
            File file = new File(uri.getPath());
            try {
                Install(file);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    @Override
    protected void onResume() {
        super.onResume();
        if(should_kill) finish();
        should_kill = true;
    }
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        if(intent==null || !intent.getAction().equals(action)) return;
        int status = intent.getExtras().getInt(PackageInstaller.EXTRA_STATUS);
        switch (status){
            case PackageInstaller.STATUS_PENDING_USER_ACTION:{
                startActivity((Intent) intent.getExtras().get(Intent.EXTRA_INTENT));
                break;
            }
            case PackageInstaller.STATUS_SUCCESS:{
                Log.i("FeiGe","应用安装成功");
                break;
            }
            case PackageInstaller.STATUS_FAILURE:{
                Log.i("FeiGe","应用安装失败");
                break;
            }
        }
    }
    public void Install(File apk) throws IOException {
        if(Build.VERSION.SDK_INT = android.os.Build.VERSION_CODES.LOLLIPOP) {
            Log.e("feige","准备为新版安卓设备安装apk...");
            Log.e("feige","安装包路径: " + apk.getAbsolutePath());
            try(OutputStream packageInSession = session.openWrite("package",0,-1);
                InputStream is = new FileInputStream(apk)
            ){
                byte[] buffer = new byte[16384];
                int n;
                while((n = is.read(buffer)) >= 0){
                    packageInSession.write(buffer,0,n);
                }
            }catch (IOException e){
                e.printStackTrace();
                Log.e("feige","传输进程出错!");
                return;
            }
            Log.e("feige","数据传输完毕");
        }
    }
    @Override
    public void onClick(View view) {
        finish();
    }
}
此部分代码在清单文件中对应的声明如下:
[XML] 纯文本查看 复制代码
            
               
            

        


image.png (170.8 KB, 下载次数: 0)
下载附件
Android Studio开发示意图
2022-10-31 19:08 上传

代码写完后,直接构建apk,找到其中的dex文件,将 AppInstaller.smail放到飞哥传输中对应的位置(保证包名和路径一致),将 e.smail  中的 b方法覆盖飞哥传输原有的。
(注:此步建议把dex传输到手机上操作,否则需要用apktool手动拆包封包,没有mt会员可以用np代替)
接下来就是修改飞哥传输的清单文件,在里面新增对AppInstaller的声明:
[XML] 纯文本查看 复制代码
            
               
            

        
同时加入允许安装未知应用的权限:
[XML] 纯文本查看 复制代码

   


image.png (200 KB, 下载次数: 0)
下载附件
注入代码后反编译的示意图
2022-10-31 19:12 上传

然后重新编译生成apk,得到的飞鸽传输就能在安卓11下直接安装接收到的apk文件了

原版:https://wwd.lanzoue.com/ipchmuqmqaj
上次的去广告成品:https://wwd.lanzoue.com/iWKLcuqmqba
修复安装功能的成品:https://wwd.lanzoue.com/ixoJ10ewts2b
修复安装功能(用了另一套代码)+底部菜单的成品:https://wwd.lanzoue.com/i4PzS0g88tcj
修复所写代码已开源,见 https://gitee.com/kbtxwer/feige-fix/

代码, 文件

ouzhzh   


zoomyou 发表于 2022-11-1 09:53
飞鸽传输,有PC版吗,是不是这个手机软件和PC可以互通联系的?

Windows上有ipmsg或者飞秋,Linux上有iptux,都是可以互通的
coolheat   

        谢谢大佬分享,这个软件很好用。
        最近发现个问题,用这个版本的app在手机之间互传文件正常,电脑往手机传文件也正常。
        
        
但是手机往电脑传送的文件,在电脑上文件修和访问改时间全变成了2106年2月7日。
       不知道是不是我的系统的问题,我用的是win10。
      
        
冥界3大法王   

飞鸽传输在手机上效果如何?使用过的说一下。
qqxiazhitmac   

楼主的技术不错,佩服,下载来试试
weixu   

此贴最大的败笔是没有配图,殊不知红花儿配绿叶?
qqxiazhitmac   

感谢分享
qiuyu2019   

谢谢分享
冥界3大法王   

感谢分享
ouzhzh   

感谢楼主分享
您需要登录后才可以回帖 登录 | 立即注册