编译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

准备工作

  1. 去telegram官网下载app,注意需要vpn才能连接到,app也同样需要vpn才可以使用。
  2. 使用手机号登录telegram app
  3. 打开https://my.telegram.org/,输入刚才在app内登录的账号如 +8618312345678,点击NEXT获取验证码,验证码会发到app内,
  4. 登录后打开 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_IDAPP_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);}}
}

去除一些代码

  1. AndroidManifest.xml中删除android:manageSpaceActivity=“org.telegram.ui.ExternalActionActivity”,防止想清除数据而没法进入系统清除的界面
  2. 全局搜索 protectionLevel=“signature” 并删除防止手机上装了telegram而权限冲突安装失败
<permission android:name="org.telegram.messenger.permission.MAPS_RECEIVE" android:protectionLevel="signature"/>

运行项目

到此项目应该会成功运行,运行完成即可登录到telegram正式服务器

如果想看tg的数据,打印log日志查看

  1. 添加依赖库
implementation 'org.apache.commons:commons-lang3:3.6'
  1. 创建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");}}
}
  1. 在Telegram\TMessagesProj\src\main\java\org\telegram\messenger\MessagesController.java中 修改
  2. 在Telegram\TMessagesProj\src\main\java\org\telegram\tgnet\ConnectionsManager.java中 修改
  3. 由于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];}
}
  1. 至此可以快乐地抓取tg数据了

接收离线推送(谷歌推送)

  1. 打开 https://console.firebase.google.com/ 注册一个账号
  2. 创建一个项目 telegram,项目创建完成后添加两个安卓应用org.telegram.messenger 和 org.telegram.messenger.beta
  3. build.gradle里替换为你的签名文件,打开项目设置,为两个应用分别添加SHA证书,SHA1和SHA256,如何获取SHA证书,看下面
  4. 打开Android studio右侧的Gradle
  5. 在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源码相关推荐

  1. NanoMsg框架|Android Studio编译NanoMsg源码

    学更好的别人, 做更好的自己. --<微卡智享> 本文长度为2184字,预计阅读6分钟 导语 前面的章节已经把NanoMsg的简介,及C#相关的NNanoMsg使用Demo已经介绍完成了, ...

  2. 使用Android Studio导入安卓源码

    1 背景 这篇文章主要说明的是用它来看源码的相关配置(该实例依据官方源码进行配置说明).在android源码中发现有一个development/tools/idegen目录,查了一下发现是生成IDE的 ...

  3. Android AOSP基础(四)Source Insight和Android Studio导入系统源码

    本文首发于微信公众号「刘望舒」 关联系列 Android AOSP基础系列 Android系统启动系列 前言 在上一篇文章Android AOSP基础(三)Android系统源码的整编和单编中,我们对 ...

  4. android 修改编译内核源码 对抗反调试

    0×00  写在前面 攻防对立.程序调试与反调试之间的对抗是一个永恒的主题.在安卓逆向工程实践中,通过修改和编译安卓内核源码来对抗反调试是一种常见的方法.但网上关于此类的资料比较少,且都是基于AOSP ...

  5. Android Studio 导入 AOSP 源码

    有了 AOSP 源码,接下来就是如何看了,可以直接文本看,可以用 Source Insight,我当然选择 Android Studio,Android Studio 是我熟悉且十分强大的工具.问题来 ...

  6. Android Studio 导入 AOSP 源码 1

    有了 AOSP 源码,接下来就是如何看了,可以直接文本看,可以用 Source Insight,我当然选择 Android Studio,Android Studio 是我熟悉且十分强大的工具.问题来 ...

  7. android studio im源码,Android Studio 导入 AOSP 源码

    有了 AOSP 源码,接下来就是如何看了,可以直接文本看,可以用 Source Insight,我当然选择 Android Studio,Android Studio 是我熟悉且十分强大的工具.问题来 ...

  8. Android Studio 简易计算机源码

    效果图: 源码: 布局样式: <?xml version="1.0" encoding="utf-8"?> <GridLayout xmlns ...

  9. Android Studio 官方示例源码地址

    2019-12-16最新 使用方法: 1.安装git (具体的百度) 2.下载命令:git clone https://github.com/android/animation-samples.git ...

最新文章

  1. 斐波那契公约数的相关证明
  2. 解决静态方法调用注入的service
  3. python 自动化框架打包_听说很多人都不会打包,教你Python实现前端自动化打包部署!...
  4. 【Alpha阶段】第六次Scrum Meeting
  5. [云炬创业学笔记]第一章创业是什么测试9
  6. 使用Hibernate 4,JPA和Maven的架构创建脚本
  7. WordPress 首页显示摘要
  8. 2014年第一季度总结报告
  9. 双指针算法基础——输出单词
  10. sap导入中文数据乱码
  11. 【Renpy】renpy游戏引擎制作的游戏拆包及汉化教程
  12. GBase xdm管理端
  13. 采用最小二乘法拟合二次、三次、四次曲线
  14. 钢网有多个种类,各自的用法都了解吗?
  15. 泊松噪声(附Matlab代码)
  16. 正弦波SFR分辨率测试卡
  17. Python将Excel表格按内容拆分为多个表格
  18. 字节字双字地址的区别
  19. linux下安装subversion1.9.5
  20. xgs芯片_了解有关XGS的所有信息

热门文章

  1. 如何判断车距:车距判断技巧图解
  2. 【观察】VxRail领跑超融合市场,揭秘背后的“幕后英雄”
  3. 最新版苹果公司开发者账户申请
  4. 使用Servlet和JSP开发Java应用程序 ----错误处理
  5. 一个P,V操作的习题
  6. 大专毕业领导diss我学历低能力差,该怼回去吗?
  7. excel 表格怎么让内容回车换行?
  8. AI作诗:诗三百·人工智能诗歌写作平台
  9. 百趣代谢组学资讯:@熬夜的年轻人代谢紊乱急救包-喝普洱茶!
  10. 达梦数据库查看表字段VARCHAR类型的长度单位是BYTE还是CHAR