#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
APK功能与布局分析脚本
分析Via浏览器的功能点和布局交互
"""

import os
import sys
import json
import zipfile
import xml.etree.ElementTree as ET
from pathlib import Path
import re

# APK文件路径
APK_PATH = r"C:\Users\CYT\Desktop\base.apk"
OUTPUT_DIR = r"C:\Users\CYT\DevEcoStudioProjects\GlanceBrowser\apk_analysis"

def create_output_dir():
    """创建输出目录"""
    os.makedirs(OUTPUT_DIR, exist_ok=True)
    os.makedirs(os.path.join(OUTPUT_DIR, 'resources'), exist_ok=True)
    os.makedirs(os.path.join(OUTPUT_DIR, 'smali'), exist_ok=True)
    os.makedirs(os.path.join(OUTPUT_DIR, 'analysis'), exist_ok=True)

def extract_apk():
    """解压APK文件"""
    print(f"正在解压APK: {APK_PATH}")
    
    with zipfile.ZipFile(APK_PATH, 'r') as zip_ref:
        # 提取AndroidManifest.xml
        if 'AndroidManifest.xml' in zip_ref.namelist():
            zip_ref.extract('AndroidManifest.xml', OUTPUT_DIR)
        
        # 提取资源文件
        for file in zip_ref.namelist():
            if file.startswith('res/') and file.endswith('.xml'):
                try:
                    zip_ref.extract(file, OUTPUT_DIR)
                except:
                    pass
        
        # 提取smali代码(classes.dex)
        for file in zip_ref.namelist():
            if file.endswith('.dex'):
                zip_ref.extract(file, OUTPUT_DIR)
        
        # 提取布局文件
        for file in zip_ref.namelist():
            if 'layout' in file and file.endswith('.xml'):
                try:
                    zip_ref.extract(file, OUTPUT_DIR)
                except:
                    pass
    
    print(f"APK解压完成,输出目录: {OUTPUT_DIR}")

def analyze_manifest():
    """分析AndroidManifest.xml"""
    manifest_path = os.path.join(OUTPUT_DIR, 'AndroidManifest.xml')
    
    if not os.path.exists(manifest_path):
        print("未找到AndroidManifest.xml")
        return None
    
    # 读取二进制XML(需要特殊处理)
    print("分析AndroidManifest.xml...")
    
    # 简单分析:读取文件内容查找关键信息
    with open(manifest_path, 'rb') as f:
        content = f.read()
    
    # 提取包名、权限等信息
    manifest_info = {
        'permissions': [],
        'activities': [],
        'services': [],
        'receivers': []
    }
    
    # 在二进制数据中搜索字符串
    content_str = content.decode('latin-1')
    
    # 查找权限
    permissions = re.findall(r'android\.permission\.([A-Z_]+)', content_str)
    manifest_info['permissions'] = list(set(permissions))
    
    # 查找Activity
    activities = re.findall(r'([a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)*)Activity', content_str)
    manifest_info['activities'] = list(set(activities))[:20]  # 限制数量
    
    return manifest_info

def analyze_layouts():
    """分析布局文件"""
    layout_dir = os.path.join(OUTPUT_DIR, 'res')
    
    if not os.path.exists(layout_dir):
        print("未找到资源目录")
        return []
    
    layouts = []
    
    # 遍历所有layout目录
    for root, dirs, files in os.walk(layout_dir):
        for file in files:
            if 'layout' in root and file.endswith('.xml'):
                layout_path = os.path.join(root, file)
                layout_name = os.path.basename(root) + '/' + file
                
                try:
                    # 读取布局文件
                    with open(layout_path, 'rb') as f:
                        content = f.read()
                    
                    # 简单分析:查找UI组件
                    content_str = content.decode('latin-1', errors='ignore')
                    
                    # 查找常见的UI组件
                    components = []
                    if 'EditText' in content_str:
                        components.append('EditText')
                    if 'Button' in content_str:
                        components.append('Button')
                    if 'ImageView' in content_str:
                        components.append('ImageView')
                    if 'TextView' in content_str:
                        components.append('TextView')
                    if 'RecyclerView' in content_str:
                        components.append('RecyclerView')
                    if 'ListView' in content_str:
                        components.append('ListView')
                    if 'WebView' in content_str:
                        components.append('WebView')
                    if 'Toolbar' in content_str:
                        components.append('Toolbar')
                    if 'BottomNavigationView' in content_str:
                        components.append('BottomNavigationView')
                    if 'DrawerLayout' in content_str:
                        components.append('DrawerLayout')
                    if 'CoordinatorLayout' in content_str:
                        components.append('CoordinatorLayout')
                    if 'AppBarLayout' in content_str:
                        components.append('AppBarLayout')
                    if 'SwipeRefreshLayout' in content_str:
                        components.append('SwipeRefreshLayout')
                    if 'ProgressBar' in content_str:
                        components.append('ProgressBar')
                    if 'SearchView' in content_str:
                        components.append('SearchView')
                    if 'FloatingActionButton' in content_str:
                        components.append('FloatingActionButton')
                    if 'CardView' in content_str:
                        components.append('CardView')
                    if 'TabLayout' in content_str:
                        components.append('TabLayout')
                    if 'ViewPager' in content_str:
                        components.append('ViewPager')
                    
                    layouts.append({
                        'name': layout_name,
                        'components': components,
                        'size': len(content)
                    })
                except Exception as e:
                    pass
    
    return layouts

def analyze_resources():
    """分析资源文件"""
    res_dir = os.path.join(OUTPUT_DIR, 'res')
    
    if not os.path.exists(res_dir):
        return {}
    
    resources = {
        'drawables': 0,
        'layouts': 0,
        'values': 0,
        'menus': 0,
        'strings': 0
    }
    
    for root, dirs, files in os.walk(res_dir):
        for file in files:
            if 'drawable' in root:
                resources['drawables'] += 1
            elif 'layout' in root:
                resources['layouts'] += 1
            elif 'values' in root:
                resources['values'] += 1
            elif 'menu' in root:
                resources['menus'] += 1
            elif 'string' in file:
                resources['strings'] += 1
    
    return resources

def analyze_dex():
    """分析DEX文件(简单分析)"""
    dex_files = []
    
    for file in os.listdir(OUTPUT_DIR):
        if file.endswith('.dex'):
            dex_path = os.path.join(OUTPUT_DIR, file)
            dex_size = os.path.getsize(dex_path)
            
            # 读取DEX文件查找类名
            with open(dex_path, 'rb') as f:
                content = f.read()
            
            content_str = content.decode('latin-1', errors='ignore')
            
            # 查找关键类
            key_classes = []
            
            # 浏览器相关类
            if 'WebView' in content_str:
                key_classes.append('WebView')
            if 'WebChromeClient' in content_str:
                key_classes.append('WebChromeClient')
            if 'WebViewClient' in content_str:
                key_classes.append('WebViewClient')
            
            # UI相关类
            if 'Activity' in content_str:
                key_classes.append('Activity')
            if 'Fragment' in content_str:
                key_classes.append('Fragment')
            if 'Adapter' in content_str:
                key_classes.append('Adapter')
            
            # 功能相关类
            if 'Bookmark' in content_str:
                key_classes.append('Bookmark')
            if 'History' in content_str:
                key_classes.append('History')
            if 'Download' in content_str:
                key_classes.append('Download')
            if 'Settings' in content_str:
                key_classes.append('Settings')
            if 'AdBlock' in content_str or 'AdBlocker' in content_str:
                key_classes.append('AdBlock')
            if 'Theme' in content_str:
                key_classes.append('Theme')
            if 'NightMode' in content_str:
                key_classes.append('NightMode')
            if 'ReaderMode' in content_str:
                key_classes.append('ReaderMode')
            if 'FindInPage' in content_str:
                key_classes.append('FindInPage')
            if 'TabManager' in content_str:
                key_classes.append('TabManager')
            
            dex_files.append({
                'name': file,
                'size': dex_size,
                'key_classes': list(set(key_classes))
            })
    
    return dex_files

def generate_analysis_report():
    """生成分析报告"""
    print("\n" + "="*60)
    print("Via浏览器APK功能与布局分析报告")
    print("="*60)
    
    # 分析各部分
    manifest_info = analyze_manifest()
    layouts = analyze_layouts()
    resources = analyze_resources()
    dex_info = analyze_dex()
    
    # 生成报告
    report = {
        'apk_path': APK_PATH,
        'manifest': manifest_info,
        'layouts': layouts,
        'resources': resources,
        'dex_info': dex_info,
        'analysis_time': str(os.path.getmtime(APK_PATH))
    }
    
    # 保存JSON报告
    report_path = os.path.join(OUTPUT_DIR, 'analysis', 'apk_analysis.json')
    with open(report_path, 'w', encoding='utf-8') as f:
        json.dump(report, f, indent=2, ensure_ascii=False)
    
    print(f"\n分析报告已保存: {report_path}")
    
    # 打印摘要
    print("\n【功能摘要】")
    print(f"- 权限数量: {len(manifest_info['permissions']) if manifest_info else 0}")
    print(f"- 布局文件数: {len(layouts)}")
    print(f"- 资源统计: {resources}")
    print(f"- DEX文件数: {len(dex_info)}")
    
    if dex_info:
        print("\n【关键功能类】")
        all_classes = set()
        for dex in dex_info:
            all_classes.update(dex['key_classes'])
        print(f"- {', '.join(sorted(all_classes))}")
    
    print("\n【布局组件统计】")
    component_count = {}
    for layout in layouts:
        for comp in layout['components']:
            component_count[comp] = component_count.get(comp, 0) + 1
    
    for comp, count in sorted(component_count.items(), key=lambda x: x[1], reverse=True):
        print(f"- {comp}: {count}次")
    
    return report

def main():
    """主函数"""
    print("开始分析Via浏览器APK...")
    
    # 检查APK文件
    if not os.path.exists(APK_PATH):
        print(f"错误: APK文件不存在: {APK_PATH}")
        return
    
    # 创建输出目录
    create_output_dir()
    
    # 解压APK
    extract_apk()
    
    # 生成分析报告
    report = generate_analysis_report()
    
    print("\n分析完成!")

if __name__ == '__main__':
    main()