android studio 编译Telegram源码
编译Telegram代码,群语音版本
- Telegram github地址
- 编译环境
- 准备工作
- 开始编译
- 拉取代码
- 检出7.6.1
- Android studio打开telegram项目
- 去除一些代码
- 运行项目
- 如果想看tg的数据,打印log日志查看
- 接收离线推送(谷歌推送)
- 注意
Telegram github地址
github: https://github.com/DrKLO/Telegram.git
编译环境
Windows 64
Android studio 4.2
ndk版本:21.1.6352462
JDK1.8
准备工作
- 去telegram官网下载app,注意需要vpn才能连接到,app也同样需要vpn才可以使用。
- 使用手机号登录telegram app
- 打开https://my.telegram.org/,输入刚才在app内登录的账号如 +8618312345678,点击NEXT获取验证码,验证码会发到app内,
- 登录后打开 API development tools,填写app名称,和shortname,比如 testapp1,选择Android,最后点击 Create application 创建完成
开始编译
拉取代码
git clone https://github.com/DrKLO/Telegram.git
检出7.6.1
我们的项目目前使用到群语音版本 7.6.1,如果是连接的是telegram的服务,不需要做服务端的,如果想自己做服务端的接口,去参考官方的api标准,
我们的app服务端是自己做的,所以群语音也需要自己做,后面会出一个自己做的群语音服务的教程,基于mediasoup,以及官方的Demo讲解。
git checkout 7ba9838a
Android studio打开telegram项目
编辑Telegram\TMessagesProj\src\main\java\org\telegram\messenger\BuildVars.java
替换你在控制台创建的获取的 APP_ID 和 APP_HASH
下面是对应修改的代码
public class BuildVars {public static boolean DEBUG_VERSION = BuildConfig.DEBUG;public static boolean DEBUG_PRIVATE_VERSION = DEBUG_VERSION;public static boolean LOGS_ENABLED = DEBUG_VERSION;public static boolean USE_CLOUD_STRINGS = true;public static boolean CHECK_UPDATES = true;public static int BUILD_VERSION = BuildConfig.VERSION_CODE;public static String BUILD_VERSION_STRING = BuildConfig.VERSION_NAME;public static int APP_ID = 1;//你的api_idpublic static String APP_HASH = "你的api_hash";//由于要在谷歌商店,必须去掉所有APPCENTER相关的库,否则被拒//public static String APPCENTER_HASH = "a5b5c4f5-51da-dedc-9918-d9766a22ca7c";//public static String APPCENTER_HASH_DEBUG = "f9726602-67c9-48d2-b5d0-4761f1c1a8f3";public static String SMS_HASH = DEBUG_VERSION ? "O2P2z+/jBpJ" : "oLeq9AcOZkT";public static String PLAYSTORE_APP_URL = "https://play.google.com/store/apps/details?id=org.telegram.messenger";static {if (ApplicationLoader.applicationContext != null) {SharedPreferences sharedPreferences = ApplicationLoader.applicationContext.getSharedPreferences("systemConfig", Context.MODE_PRIVATE);LOGS_ENABLED = sharedPreferences.getBoolean("logsEnabled", DEBUG_VERSION);}}
}
去除一些代码
- AndroidManifest.xml中删除android:manageSpaceActivity=“org.telegram.ui.ExternalActionActivity”,防止想清除数据而没法进入系统清除的界面
- 全局搜索 protectionLevel=“signature” 并删除防止手机上装了telegram而权限冲突安装失败
<permission android:name="org.telegram.messenger.permission.MAPS_RECEIVE" android:protectionLevel="signature"/>
运行项目
到此项目应该会成功运行,运行完成即可登录到telegram正式服务器
如果想看tg的数据,打印log日志查看
- 添加依赖库
implementation 'org.apache.commons:commons-lang3:3.6'
- 创建RecursiveToStringStyle.java,将tg数据转为字符串并格式化
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.telegram.messenger.FileLog;import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class RecursiveToStringStyle extends ToStringStyle {private final int maxDepth;private int depth;private final String tabs;public RecursiveToStringStyle(int maxDepth) {this.maxDepth = maxDepth;this.depth = 0;tabs = StringUtils.repeat("\t", maxDepth);setUseShortClassName(true);setUseIdentityHashCode(false);this.setArrayStart("");this.setArrayEnd("");this.setArraySeparator(", ");this.setNullText("null");this.setSummaryObjectStartText("\"<");this.setSummaryObjectEndText(">\"");setContentStart(" {");setFieldSeparator(",\n");setFieldSeparatorAtStart(true);setFieldNameValueSeparator(": ");setContentEnd("}");}public static String toString(Object value) {if (value == null)return "null";final StringBuffer sb = new StringBuffer(512);RecursiveToStringStyle ins = new RecursiveToStringStyle(13);ins.appendDetail(sb, null, value);return sb.toString();}private int getDepth() {return Math.min(this.maxDepth, this.depth);}private void padDepth(StringBuffer buffer) {buffer.append(tabs, 0, getDepth());}private StringBuffer appendTabified(StringBuffer buffer, String value) {Matcher matcher = Pattern.compile("\n").matcher(value);String replacement = "\n" + tabs.substring(0, getDepth());while (matcher.find()) {matcher.appendReplacement(buffer, replacement);}matcher.appendTail(buffer);return buffer;}@Overrideprotected void appendFieldSeparator(StringBuffer buffer) {buffer.append(getFieldSeparator());padDepth(buffer);}@Overridepublic void appendStart(StringBuffer buffer, Object object) {this.depth++;// 开头特殊处理boolean is_array = object != null && object.getClass().isArray();if(object != null) {if (is_array) {buffer.append("[");} else {appendClassName(buffer, object);// 类名后添加constructorint constructor = 0;String classname = object.getClass().getSimpleName();if (classname.contains("TL_")) {try {Class clz = object.getClass();constructor = clz.getDeclaredField("constructor").getInt(clz);buffer.append("("+constructor+")");buffer.append("#"+Integer.toHexString(constructor));} catch(Exception e) {FileLog.e(e);}}appendContentStart(buffer);}buffer.append("\n");padDepth(buffer);}}@Overridepublic void appendEnd(StringBuffer buffer, Object object) {// 数组结尾特殊处理boolean is_array = object != null && object.getClass().isArray();boolean is_empty_array = is_array && ((Object[])object).length <= 0;super.appendEnd(buffer, object);buffer.setLength(buffer.length() - getContentEnd().length());if (!is_empty_array) {buffer.append("\n");}this.depth--;if (!is_empty_array) {padDepth(buffer);}if (is_array) {buffer.append("]");} else {appendContentEnd(buffer);}}@Overrideprotected void removeLastFieldSeparator(StringBuffer buffer) {int n = 0;for (int i=buffer.length()-1; i>=0; i--) {if (Character.isWhitespace(buffer.charAt(i))) {n += 1;} else {break;}}buffer.setLength(buffer.length() - n);}private boolean noReflectionNeeded(Object value) {try {return value != null &&(value.getClass().getName().startsWith("java.lang.")|| value.getClass().getMethod("toString").getDeclaringClass() != Object.class);} catch (NoSuchMethodException e) {throw new IllegalStateException(e);}}@Overrideprotected void appendDetail(StringBuffer buffer, String fieldName, Object value) {if (getDepth() >= maxDepth || noReflectionNeeded(value)) {appendTabified(buffer, String.valueOf(value));} else {new ReflectionToStringBuilder(value, this, buffer, null, false, false).toString();}}@Overrideprotected void appendDetail(StringBuffer buffer, String fieldName, Collection<?> coll) {buffer.append(ReflectionToStringBuilder.toString(coll.toArray(), this, true, true));}public void append(final StringBuffer buffer, final String fieldName, final Object value, final Boolean fullDetail) {// 无用字段不打印if (fieldName == "disableFree" || fieldName == "networkType") {return;}// 字符串加引号if (value instanceof String) {String v = "\"" + (String)value + "\"";super.append(buffer, fieldName, v, fullDetail);} else {super.append(buffer, fieldName, value, fullDetail);}}protected void appendInternal(final StringBuffer buffer, final String fieldName, final Object value, final boolean detail) {super.appendInternal(buffer, fieldName, value, detail);// 特殊类型需要显示打印出来便于观察if (value instanceof Long) {buffer.append(" LONG");}}
}
- 在Telegram\TMessagesProj\src\main\java\org\telegram\messenger\MessagesController.java中 修改
- 在Telegram\TMessagesProj\src\main\java\org\telegram\tgnet\ConnectionsManager.java中 修改
- 由于log过长可能打印不全,修改Telegram\TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java
/** This is the source code of Telegram for Android v. 5.x.x.* It is licensed under GNU GPL v. 2 or later.* You should have received a copy of the license in this archive (see LICENSE).** Copyright Nikolai Kudashov, 2013-2018.*/package org.telegram.messenger;import android.text.TextUtils;
import android.util.Log;import org.telegram.messenger.time.FastDateFormat;import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.Locale;public class FileLog {private OutputStreamWriter streamWriter = null;private FastDateFormat dateFormat = null;private DispatchQueue logQueue = null;private File currentFile = null;private File networkFile = null;private File tonlibFile = null;private boolean initied;private final static String tag = "tmessages";private static volatile FileLog Instance = null;public static FileLog getInstance() {FileLog localInstance = Instance;if (localInstance == null) {synchronized (FileLog.class) {localInstance = Instance;if (localInstance == null) {Instance = localInstance = new FileLog();}}}return localInstance;}public FileLog() {if (!BuildVars.LOGS_ENABLED) {return;}init();}public void init() {if (initied) {return;}dateFormat = FastDateFormat.getInstance("dd_MM_yyyy_HH_mm_ss", Locale.US);try {File sdCard = ApplicationLoader.applicationContext.getExternalFilesDir(null);if (sdCard == null) {return;}File dir = new File(sdCard.getAbsolutePath() + "/logs");dir.mkdirs();currentFile = new File(dir, dateFormat.format(System.currentTimeMillis()) + ".txt");} catch (Exception e) {e.printStackTrace();}try {logQueue = new DispatchQueue("logQueue");currentFile.createNewFile();FileOutputStream stream = new FileOutputStream(currentFile);streamWriter = new OutputStreamWriter(stream);streamWriter.write("-----start log " + dateFormat.format(System.currentTimeMillis()) + "-----\n");streamWriter.flush();} catch (Exception e) {e.printStackTrace();}initied = true;}public static void ensureInitied() {getInstance().init();}public static String getNetworkLogPath() {if (!BuildVars.LOGS_ENABLED) {return "";}try {File sdCard = ApplicationLoader.applicationContext.getExternalFilesDir(null);if (sdCard == null) {return "";}File dir = new File(sdCard.getAbsolutePath() + "/logs");dir.mkdirs();getInstance().networkFile = new File(dir, getInstance().dateFormat.format(System.currentTimeMillis()) + "_net.txt");return getInstance().networkFile.getAbsolutePath();} catch (Throwable e) {e.printStackTrace();}return "";}public static String getTonlibLogPath() {if (!BuildVars.LOGS_ENABLED) {return "";}try {File sdCard = ApplicationLoader.applicationContext.getExternalFilesDir(null);if (sdCard == null) {return "";}File dir = new File(sdCard.getAbsolutePath() + "/logs");dir.mkdirs();getInstance().tonlibFile = new File(dir, getInstance().dateFormat.format(System.currentTimeMillis()) + "_tonlib.txt");return getInstance().tonlibFile.getAbsolutePath();} catch (Throwable e) {e.printStackTrace();}return "";}public static void e(final String message, final Throwable exception) {if (!BuildVars.LOGS_ENABLED) {return;}ensureInitied();Log.e(tag, message, exception);if (getInstance().streamWriter != null) {getInstance().logQueue.postRunnable(() -> {try {getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/tmessages: " + message + "\n");getInstance().streamWriter.write(exception.toString());getInstance().streamWriter.flush();} catch (Exception e) {e.printStackTrace();}});}}public static void e(final String message) {if (!BuildVars.LOGS_ENABLED) {return;}ensureInitied();logger("e",message);if (getInstance().streamWriter != null) {getInstance().logQueue.postRunnable(() -> {try {getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/tmessages: " + message + "\n");getInstance().streamWriter.flush();} catch (Exception e) {e.printStackTrace();}});}}public static void e(final Throwable e) {if (!BuildVars.LOGS_ENABLED) {return;}ensureInitied();e.printStackTrace();if (getInstance().streamWriter != null) {getInstance().logQueue.postRunnable(() -> {try {getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/tmessages: " + e + "\n");StackTraceElement[] stack = e.getStackTrace();for (int a = 0; a < stack.length; a++) {getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/tmessages: " + stack[a] + "\n");}getInstance().streamWriter.flush();} catch (Exception e1) {e1.printStackTrace();}});} else {e.printStackTrace();}}public static void d(final String message) {if (!BuildVars.LOGS_ENABLED) {return;}ensureInitied();logger("d",message);if (getInstance().streamWriter != null) {getInstance().logQueue.postRunnable(() -> {try {getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " D/tmessages: " + message + "\n");getInstance().streamWriter.flush();} catch (Exception e) {e.printStackTrace();}});}}public static void w(final String message) {if (!BuildVars.LOGS_ENABLED) {return;}ensureInitied();logger("w",message);if (getInstance().streamWriter != null) {getInstance().logQueue.postRunnable(() -> {try {getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " W/tmessages: " + message + "\n");getInstance().streamWriter.flush();} catch (Exception e) {e.printStackTrace();}});}}public static void cleanupLogs() {ensureInitied();File sdCard = ApplicationLoader.applicationContext.getExternalFilesDir(null);if (sdCard == null) {return;}File dir = new File (sdCard.getAbsolutePath() + "/logs");File[] files = dir.listFiles();if (files != null) {for (int a = 0; a < files.length; a++) {File file = files[a];if (getInstance().currentFile != null && file.getAbsolutePath().equals(getInstance().currentFile.getAbsolutePath())) {continue;}if (getInstance().networkFile != null && file.getAbsolutePath().equals(getInstance().networkFile.getAbsolutePath())) {continue;}if (getInstance().tonlibFile != null && file.getAbsolutePath().equals(getInstance().tonlibFile.getAbsolutePath())) {continue;}file.delete();}}}public static String tagPrefix = "FileLog";//log前缀/**** @param type logger级别* @param o logger内容*/private static void logger(String type, String o) {if (!BuildVars.DEBUG_VERSION) {return;}String msg=o+"";String tag = getTag(getCallerStackTraceElement());truncation(type,tag,msg);}/*** 截断输出日志* @param msg*/private static void truncation(String type,String tag, String msg) {if (tag == null || tag.length() == 0|| msg == null || msg.length() == 0)return;int segmentSize = 3 * 1024;long length = msg.length();if (length <= segmentSize ) {// 长度小于等于限制直接打印logPrint(type,tag, msg);}else {while (msg.length() > segmentSize ) {// 循环分段打印日志String logContent = msg.substring(0, segmentSize );msg = msg.replace(logContent, "");logPrint(type,tag, logContent);}logPrint(type,tag, msg);// 打印剩余日志}}private static void logPrint(String type,String tag,String msg){switch (type){case "i":Log.i(tag,msg);case "d":Log.d(tag,msg);break;case "e":Log.e(tag,msg);break;case "w":Log.w(tag,msg);break;}}private static String getTag(StackTraceElement element) {String tag = "%s.%s(Line:%d)"; // 占位符String callerClazzName = element.getClassName(); // 获取到类名callerClazzName = callerClazzName.substring(callerClazzName.lastIndexOf(".") + 1);tag = String.format(tag, callerClazzName, element.getMethodName(),element.getLineNumber()); // 替换tag = TextUtils.isEmpty(tagPrefix) ? tag : tagPrefix + ":"+ tag;return tag;}/*** 获取线程状态* @return*/private static StackTraceElement getCallerStackTraceElement() {return Thread.currentThread().getStackTrace()[5];}
}
- 至此可以快乐地抓取tg数据了
接收离线推送(谷歌推送)
- 打开 https://console.firebase.google.com/ 注册一个账号
- 创建一个项目 telegram,项目创建完成后添加两个安卓应用org.telegram.messenger 和 org.telegram.messenger.beta
- build.gradle里替换为你的签名文件,打开项目设置,为两个应用分别添加SHA证书,SHA1和SHA256,如何获取SHA证书,看下面
- 打开Android studio右侧的Gradle
- 在firebase控制台,项目配置-》云消息传递,复制密钥,然后打开https://my.telegram.org/apps,配置GCM API key,就是刚才复制的key保存就ok了
注意
如果想编译其他版本,低于 7.1.0 的版本windows上是编译不了的,因为目录太长,超过了windows的最大长度限制,解决办法,下载 VMware 创建ubuntu虚拟机,编译过程都是一样的
第一次写博客,嗨,dia,dia,dia,万能秘籍,上上下下,左右左右,BABA~
android studio 编译Telegram源码相关推荐
- NanoMsg框架|Android Studio编译NanoMsg源码
学更好的别人, 做更好的自己. --<微卡智享> 本文长度为2184字,预计阅读6分钟 导语 前面的章节已经把NanoMsg的简介,及C#相关的NNanoMsg使用Demo已经介绍完成了, ...
- 使用Android Studio导入安卓源码
1 背景 这篇文章主要说明的是用它来看源码的相关配置(该实例依据官方源码进行配置说明).在android源码中发现有一个development/tools/idegen目录,查了一下发现是生成IDE的 ...
- Android AOSP基础(四)Source Insight和Android Studio导入系统源码
本文首发于微信公众号「刘望舒」 关联系列 Android AOSP基础系列 Android系统启动系列 前言 在上一篇文章Android AOSP基础(三)Android系统源码的整编和单编中,我们对 ...
- android 修改编译内核源码 对抗反调试
0×00 写在前面 攻防对立.程序调试与反调试之间的对抗是一个永恒的主题.在安卓逆向工程实践中,通过修改和编译安卓内核源码来对抗反调试是一种常见的方法.但网上关于此类的资料比较少,且都是基于AOSP ...
- Android Studio 导入 AOSP 源码
有了 AOSP 源码,接下来就是如何看了,可以直接文本看,可以用 Source Insight,我当然选择 Android Studio,Android Studio 是我熟悉且十分强大的工具.问题来 ...
- Android Studio 导入 AOSP 源码 1
有了 AOSP 源码,接下来就是如何看了,可以直接文本看,可以用 Source Insight,我当然选择 Android Studio,Android Studio 是我熟悉且十分强大的工具.问题来 ...
- android studio im源码,Android Studio 导入 AOSP 源码
有了 AOSP 源码,接下来就是如何看了,可以直接文本看,可以用 Source Insight,我当然选择 Android Studio,Android Studio 是我熟悉且十分强大的工具.问题来 ...
- Android Studio 简易计算机源码
效果图: 源码: 布局样式: <?xml version="1.0" encoding="utf-8"?> <GridLayout xmlns ...
- Android Studio 官方示例源码地址
2019-12-16最新 使用方法: 1.安装git (具体的百度) 2.下载命令:git clone https://github.com/android/animation-samples.git ...
最新文章
- 斐波那契公约数的相关证明
- 解决静态方法调用注入的service
- python 自动化框架打包_听说很多人都不会打包,教你Python实现前端自动化打包部署!...
- 【Alpha阶段】第六次Scrum Meeting
- [云炬创业学笔记]第一章创业是什么测试9
- 使用Hibernate 4,JPA和Maven的架构创建脚本
- WordPress 首页显示摘要
- 2014年第一季度总结报告
- 双指针算法基础——输出单词
- sap导入中文数据乱码
- 【Renpy】renpy游戏引擎制作的游戏拆包及汉化教程
- GBase xdm管理端
- 采用最小二乘法拟合二次、三次、四次曲线
- 钢网有多个种类,各自的用法都了解吗?
- 泊松噪声(附Matlab代码)
- 正弦波SFR分辨率测试卡
- Python将Excel表格按内容拆分为多个表格
- 字节字双字地址的区别
- linux下安装subversion1.9.5
- xgs芯片_了解有关XGS的所有信息