Merge pull request #58 from xianglin1998/master

PM3 res updated.
This commit is contained in:
DXL
2020-10-26 16:32:22 +08:00
committed by GitHub
132 changed files with 8302 additions and 1586 deletions
+5 -9
View File
@@ -52,14 +52,11 @@ dependencies {
annotationProcessor 'com.github.bumptech.glide:compiler:4.5.0'
// This my project maven from github release!
implementation 'com.github.xianglin1998:IORedirector:1.0'
implementation 'com.github.xianglin1998:Crapto1:1.3'
implementation 'com.github.xianglin1998:nfctag:1.0'
implementation 'com.github.xianglin1998:nfc_console:1.0'
implementation 'com.github.xianglin1998:ComBridge:1.0.7'
// implementation project(path: ':iobridges')
implementation project(path: ':iobridges')
implementation project(path: ':crapto1')
implementation project(path: ':nfctag')
implementation project(path: ':console')
implementation project(path: ':redirector')
implementation project(':utils')
implementation project(':libnfc_pn53x')
@@ -68,7 +65,6 @@ dependencies {
implementation project(path: ':pm3flasher')
implementation project(':pm3rdv4rrg')
implementation project(path: ':xmodem')
// The dep from TERMUX(A FullTerminal implements.)
implementation project(":termux-app")
-2
View File
@@ -35,9 +35,7 @@
</activity>
<activity android:name=".activities.tools.KeyFileEditActivity" />
<activity android:name=".activities.tools.DumpEqualActivity" />
<activity android:name=".activities.tools.DumpEditActivity" />
<activity android:name=".activities.tools.FormatCovertActivity" />
<activity android:name=".activities.tools.ChameleonSoltAliasesActivity" />
<activity android:name=".activities.tools.AboutActicity" />
-87
View File
@@ -1,87 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<style>
*{
padding: 0px;
margin: 0px;
}
ul,li{
list-style: none;
}
body{
background:#05A1FF;
font: "宋体" 16px;
color: white;
}
.title{
padding: 6px;
}
.devlist,.comlist{
text-indent:2em;
line-height: 33px;
border: solid 1px white;
border-bottom: none;
border-radius: 3px;
margin: 2px;
}
.devlist li{
border-bottom: solid 1px white;
}
.comlist li{
border-bottom: solid 1px white;
}
.itemTitle{
padding:6px;
background: #0097F3;
}
</style>
<meta charset="UTF-8"/>
<title>使用帮助</title>
</head>
<body>
<h3 align="center" class="title">前言</h3>
<p class="itemTitle">本APP支持哪些设备?</p>
<ul class="devlist">
<li>1、恩智浦_自带(免费)</li>
<li>2、恩智浦_PN532(付费)</li>
<li>3、龙杰_ACR122U(付费)</li>
<li>4、Proxmark3CDC(付费)</li>
<li>5、ChameleonCDC(付费)</li>
<li>6、Proxmark3SPP(付费)</li>
</ul>
<p class="itemTitle">本APP支持哪些连接方式?</p>
<ul class="comlist">
<li>1、OTG</li>
<li>2、蓝牙</li>
</ul>
<p class="itemTitle">APP注意事项正文</p>
<p style="text-indent:2em; margin: 6px;">
1、Miui系统可能需要前往权限管理打开“后台弹出窗口”,否则一键重启不可用!
</p>
<p style="text-indent:2em; margin: 6px;">
2、没有购买权限是无法发现相关设备的,请有需要的用户联系管理员购买!
</p>
<p style="text-indent:2em; margin: 6px;">
3、为了您的数据安全,APP不允许您以Wifi代理或者VPN之类的方式联网!
</p>
<p style="text-indent:2em; margin: 6px;">
4、很多权限都是谷歌附加强调的,但APP本身并未使用,比如定位,此链接可证实:<a href="http://sina.lt/gpyF">cnblogs</a>
如果您没有使用蓝牙相关的设备,您完全可以禁止本APP的定位权限,身正不怕影子斜!
</p>
<p style="text-indent:2em; margin: 6px;">
5、目前已知的问题是后台一段时间后会被回收内存,导致程序出错,所以在处理任务时请不要轻易切换后台!
</p>
<p style="text-indent:2em; margin: 6px;">
6、出现问题请在“加入Q群”中进群反馈,必要时提供log文件,在“发送log”选项中,
选择log时请选择发送最顶端的带有数字的比如“log_1557477240504”,最好是多发几个。
</p>
<p class="itemTitle">APP使用帮助正文</p>
<p style="text-indent:2em; margin: 6px;">
本APP在线帮助与免责声明已经整理好一部分,本APP涉及到的开源库将被共享到此链接,如果未发现,可能是操作未更新,可联系dev要求更新。<a
href="http://www.pn532.com/?id=21">跳转观看</a></p>
</body>
</html>
+10
View File
@@ -0,0 +1,10 @@
20201026_5
pattern: *_*
frist *: date
second: number
example: 20201026_1
example: 20201026_2
example: 20201027_1
Binary file not shown.
@@ -18,7 +18,7 @@ import android.widget.ListView;
import android.widget.TextView;
import com.iobridges.com.Communication;
import com.proxgrind.xmodem.XModem128;
import cn.rrg.chameleon.xmodem.XModem128;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -80,10 +80,12 @@ public class Proxmark3NewTerminalInitActivity extends BaseActivity {
box.setChecked(Commons.getAutoGoToTerminal());
// Must have init pm3 client and check auto go and have the terminal type selected!
if (Commons.getAutoGoToTerminal()
&& Commons.isPM3ClientDecompressed()
&& Commons.getTerminalType() != -1) {
go();
if (Commons.getAutoGoToTerminal() && Commons.getTerminalType() != -1) {
if (Proxmark3Installer.isCanInstall(activity)) {
Proxmark3Installer.installIfNeed(activity, this::go);
} else {
go();
}
}
}
@@ -1,42 +1,22 @@
package cn.rrg.rdv.activities.tools;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import android.view.View;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import cn.dxl.common.util.AppUtil;
import cn.dxl.common.util.FileUtils;
import cn.dxl.common.widget.FilesSelectorDialog;
import cn.rrg.rdv.R;
import cn.rrg.rdv.activities.main.BaseActivity;
import cn.rrg.rdv.util.Commons;
import cn.rrg.rdv.util.Paths;
import cn.dxl.common.util.RestartUtils;
import cn.dxl.common.widget.ToastUtil;
public class AboutActicity extends BaseActivity {
private TextView txtUserHelp = null;
private TextView txtDisclaimer = null;
private TextView txtJoinGroup = null;
private TextView txtContactDev = null;
private TextView txtShowVersion = null;
private TextView txtSendLogFile = null;
private TextView txtCleanData = null;
private Button btnGo2ProxgrindWebsite;
private Button btnGo2RRGWebsite;
@@ -51,105 +31,13 @@ public class AboutActicity extends BaseActivity {
}
private void initViews() {
txtUserHelp = findViewById(R.id.txtUserHelp);
txtDisclaimer = findViewById(R.id.txtDisclaimer);
txtJoinGroup = findViewById(R.id.txtJoinQQGroup);
txtContactDev = findViewById(R.id.txtContactDev);
txtShowVersion = findViewById(R.id.txtShowAppVersion);
txtSendLogFile = findViewById(R.id.txtSendLogFile);
txtCleanData = findViewById(R.id.txtCleanData);
btnGo2ProxgrindWebsite = findViewById(R.id.btnGo2ProxgrindWebsite);
btnGo2RRGWebsite = findViewById(R.id.btnGo2RRGWebsite);
}
private void initActions() {
txtUserHelp.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//建立视图
WebView wv = new WebView(AboutActicity.this);
//加载文件
wv.loadUrl("file:///android_asset/help.html");
//加载进对话框中
new AlertDialog.Builder(AboutActicity.this)
.setView(wv).show();
}
});
txtDisclaimer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
txtJoinGroup.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean result = joinQQGroup("4QQrqUHKMNZDNWLvi4kEWeEDHYMekp7x");
if (!result) {
Toast.makeText(AboutActicity.this, "未安装手Q或安装的版本不支持!", Toast.LENGTH_SHORT).show();
}
}
});
txtContactDev.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Commons.callQQ(AboutActicity.this, "64101226", new Runnable() {
@Override
public void run() {
ToastUtil.show(context, getString(R.string.error), false);
}
});
}
});
txtSendLogFile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new FilesSelectorDialog.Builder(AboutActicity.this)
.setPathOnLoad(Paths.LOG_DIRECTORY)
.setTitle(R.string.logList)
.setOnSelectListener(new FilesSelectorDialog.OnSelectListener() {
@Override
public void selected(File file) {
FileUtils.shareFile(file);
}
})
.create().show();
}
});
txtCleanData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new AlertDialog.Builder(AboutActicity.this)
.setTitle(R.string.warning)
.setMessage(R.string.tipls_clearData)
.setPositiveButton(getString(R.string.clear), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(AboutActicity.this, getString(R.string.cleaning), Toast.LENGTH_SHORT).show();
FileUtils.delete(new File(Paths.TOOLS_DIRECTORY));
Toast.makeText(AboutActicity.this, getString(R.string.clearFinish), Toast.LENGTH_SHORT).show();
//必须重启APP
RestartUtils.restartAPP(AboutActicity.this, 1000, new RestartUtils.OnExitAction() {
@Override
public boolean usingSystemExit() {
//调用act管理器结束所有的活动!
AppUtil.getInstance().finishAll();
return false;
}
});
AppUtil.getInstance().finishAll();
}
})
.setNegativeButton(R.string.cancel, null)
.show();
}
});
btnGo2ProxgrindWebsite.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -177,27 +65,6 @@ public class AboutActicity extends BaseActivity {
}
}
/****************
*
* 发起添加群流程。群号:NFC PN532 计算机 单片机(573359551) 的 key 为: 4QQrqUHKMNZDNWLvi4kEWeEDHYMekp7x
* 调用 joinQQGroup(4QQrqUHKMNZDNWLvi4kEWeEDHYMekp7x) 即可发起手Q客户端申请加群 NFC PN532 计算机 单片机(573359551)
*
* @param key 由官网生成的key
* @return 返回true表示呼起手Q成功,返回fals表示呼起失败
******************/
public boolean joinQQGroup(String key) {
Intent intent = new Intent();
intent.setData(Uri.parse("mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D" + key));
// 此Flag可根据具体产品需要自定义,如设置,则在加群界面按返回,返回手Q主界面,不设置,按返回会返回到呼起产品界面 //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
try {
startActivity(intent);
return true;
} catch (Exception e) {
// 未安装手Q或安装的版本不支持
return false;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
@@ -1,220 +0,0 @@
package cn.rrg.rdv.activities.tools;
import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.Nullable;
import android.view.View;
import android.widget.ListView;
import android.widget.RadioGroup;
import android.widget.TextView;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import cn.dxl.common.widget.FilesSelectorDialog;
import cn.rrg.rdv.R;
import cn.rrg.rdv.activities.main.BaseActivity;
import cn.rrg.rdv.adapter.DumpEqualAdapter;
import cn.rrg.rdv.javabean.M1Bean;
import cn.rrg.rdv.presenter.FileReadLinePresenter;
import cn.rrg.rdv.view.FileReadLineView;
import cn.rrg.rdv.util.Commons;
import cn.rrg.rdv.util.LineEqualUtil;
import cn.rrg.rdv.util.Paths;
import cn.dxl.common.util.ArrayUtils;
import cn.dxl.common.widget.ToastUtil;
public class DumpEqualActivity extends BaseActivity implements FileReadLineView {
private RadioGroup radioGroupPathSelect = null;
private TextView txtSelectData1 = null;
private TextView txtSelectData2 = null;
private TextView txtShowEqualMsg = null;
private DumpEqualAdapter adapter = null;
private ArrayList<String> mData1 = new ArrayList<>();
private ArrayList<String> mData2 = new ArrayList<>();
private FilesSelectorDialog mSelector = null;
private int fileId = 1;
private FileReadLinePresenter presenter = null;
//初始化给两个必须要的参数!
private boolean[] states = {false, false};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
setContentView(R.layout.act_dump_equal);
super.onCreate(savedInstanceState);
presenter = new FileReadLinePresenter();
presenter.attachView(this);
//初始化视图
initViews();
//初始化动作!
initActions();
//看看能否取得传递过来的数据!
Intent intent = getIntent();
//取出数据进行转换!
ArrayList<M1Bean> dataList = (ArrayList<M1Bean>) intent.getSerializableExtra("dataList");
//进行判断!
if (dataList != null) {
//取出数据名字!
String name = intent.getStringExtra("dataName");
if (name != null) {
txtSelectData1.setText(name);
} else {
txtSelectData1.setText(R.string.data_name_dafault);
}
ArrayList<String> data = new ArrayList<>(128);
//进行拼接!
for (M1Bean bean : dataList) {
//进行拼接!
data.addAll(Arrays.asList(bean.getDatas()));
}
//设置ID
fileId = 1;
onReadFinish(ArrayUtils.list2Arr(data));
}
}
private void initViews() {
radioGroupPathSelect = findViewById(R.id.rdoGroupDataPath);
txtSelectData1 = findViewById(R.id.txtDumpEqualData1);
txtSelectData2 = findViewById(R.id.txtDumpEqualData2);
txtShowEqualMsg = findViewById(R.id.txtShowEqualMsg);
ListView lvShowEqualResult = findViewById(R.id.lvShowEqualResult);
adapter = new DumpEqualAdapter(this, R.layout.dump_equal_result_item);
lvShowEqualResult.setAdapter(adapter);
mSelector = new FilesSelectorDialog.Builder(this).setPathOnLoad(Paths.DUMP_DIRECTORY).create();
}
private void initActions() {
txtSelectData1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String path = Commons.getCustomerPath(radioGroupPathSelect);
mSelector.setPathOnLoad(path);
mSelector.setOnSelectListener(new FilesSelectorDialog.OnSelectListener() {
@Override
public void selected(File file) {
fileId = 1;
txtSelectData1.setText(file.getName());
presenter.load(file);
}
});
mSelector.show();
}
});
txtSelectData2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String path = Commons.getCustomerPath(radioGroupPathSelect);
mSelector.setPathOnLoad(path);
mSelector.setOnSelectListener(new FilesSelectorDialog.OnSelectListener() {
@Override
public void selected(File file) {
fileId = 2;
txtSelectData2.setText(file.getName());
presenter.load(file);
}
});
mSelector.show();
}
});
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onDestroy() {
presenter.detachView();
//清除数据,帮助回收!
mData1.clear();
mData2.clear();
adapter.clear();
super.onDestroy();
}
@Override
public void onReadFinish(String[] line) {
//加载成功了,需要进行判断当前是哪个文件加载出来的!
switch (fileId) {
//进行处理!
case 1:
//第一个数据!
mData1.clear();
mData1.addAll(Arrays.asList(line));
states[0] = true;
break;
case 2:
//第二个数据!
mData2.clear();
mData2.addAll(Arrays.asList(line));
states[1] = true;
break;
default:
break;
}
//进行判断,如果两个数据皆正常,则直接开始计算判断!
boolean canStart = true;
for (boolean state : states) {
if (!state) {
canStart = false;
break;
}
}
if (canStart) {
//已经可以进行对比!
LineEqualUtil leu = new LineEqualUtil();
leu.putData(ArrayUtils.list2Arr(mData1), ArrayUtils.list2Arr(mData2));
String[] result = leu.finalResult();
int blockDiffCount = leu.getBlockDiffCount();
int allDiffCount = leu.getAllDiffCount();
runOnUiThread(new Runnable() {
@Override
public void run() {
String msg = getString(R.string.data_block_diff_count) + blockDiffCount + getString(R.string.data_char_diff_count) + allDiffCount;
txtShowEqualMsg.setText(msg);
//显示一些必要的弹窗
if (blockDiffCount == 0 && allDiffCount == 0) {
showToast(getString(R.string.data_identical));
}
//必须先清除之前的数据
adapter.clear();
adapter.addAll(result);
adapter.notifyDataSetChanged();
}
});
}
}
@Override
public void onReadFail(String msg) {
showToast(msg);
}
@Override
public void showToast(String msg) {
runOnUiThread(new Runnable() {
@Override
public void run() {
ToastUtil.show(DumpEqualActivity.this, msg, false);
}
});
}
@Override
public void showDialog(String title, String msg) {
}
@Override
public void hideDialog() {
}
}
@@ -1,289 +0,0 @@
package cn.rrg.rdv.activities.tools;
import android.app.AlertDialog;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;
import cn.dxl.common.widget.FilesSelectorDialog;
import cn.rrg.rdv.R;
import java.io.File;
import cn.rrg.rdv.activities.main.BaseActivity;
import cn.rrg.rdv.presenter.FormatConvertPresenter;
import cn.rrg.rdv.view.FormatConvertView;
import cn.rrg.rdv.util.Commons;
import cn.rrg.rdv.util.Paths;
import cn.dxl.common.util.StringUtil;
public class FormatCovertActivity extends BaseActivity implements FormatConvertView {
private int mType = 0;
//中介者对象持有
private FormatConvertPresenter presenter = null;
//文件选择器对象
private FilesSelectorDialog mSelector = null;
private RadioGroup radioGroupPathSelect = null;
private Button btnSelectFromQQ = null;
private Button btnSelectFromWecat = null;
private Button btnSelectFromSdcard = null;
private Button btnSelectFromThiz = null;
private Button btnSelectFromMCT = null;
private Button btnSelectFromMTools = null;
private Button btnCovert2Bin = null;
private Button btnCovert2Txt = null;
private TextView txtSelectFormAnywhere = null;
private TextView txtShowFormatDiffrences = null;
private EditText edtInputSaveName = null;
private String mSourceFilePath = null;
private String mSaveFileName = null;
private String mSavePath = null;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
setContentView(R.layout.act_format_convert);
super.onCreate(savedInstanceState);
//初始化中介者对象
presenter = new FormatConvertPresenter();
//绑定视图
presenter.attachView(this);
//初始化视图
initViews();
//初始化文件选择器
initSelector();
//初始化动作!
initActions();
}
private void initViews() {
radioGroupPathSelect = findViewById(R.id.rdoGroupDataPath);
btnSelectFromQQ = findViewById(R.id.btnDumpSelectFromQQ);
btnSelectFromSdcard = findViewById(R.id.btnDumpSelectFromSdcard);
btnSelectFromWecat = findViewById(R.id.btnDumpSelectFromWecat);
btnSelectFromThiz = findViewById(R.id.btnDumpSelectFromThis);
btnSelectFromMCT = findViewById(R.id.btnDumpSelectFromMCT);
btnSelectFromMTools = findViewById(R.id.btnDumpSelectFromMTools);
btnCovert2Bin = findViewById(R.id.btnConvert2Bin);
btnCovert2Txt = findViewById(R.id.btnConvert2Txt);
TextView txtSaveToAnywhere = findViewById(R.id.txtSaveToAnywhere);
txtSelectFormAnywhere = findViewById(R.id.txtSelectFormAnywhere);
txtShowFormatDiffrences = findViewById(R.id.txtShowFormatDiffences);
edtInputSaveName = findViewById(R.id.edtInputFileName);
Toolbar mToolbar = findViewById(R.id.toolbar_act_format_convert);
mToolbar.setTitle(R.string.title_format_convert);
setSupportActionBar(mToolbar);
}
private void initActions() {
btnSelectFromThiz.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mSelector.setPathOnLoad(Paths.DUMP_DIRECTORY);
initSourceFileSelector();
}
});
btnSelectFromSdcard.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mSelector.setPathOnLoad(Paths.EXTERNAL_STORAGE_DIRECTORY);
initSourceFileSelector();
}
});
btnSelectFromQQ.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mSelector.setPathOnLoad(Paths.QQ_DIRECTORY);
initSourceFileSelector();
}
});
btnSelectFromWecat.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mSelector.setPathOnLoad(Paths.WECAT_DIRECTORY);
initSourceFileSelector();
}
});
btnSelectFromMCT.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mSelector.setPathOnLoad(Paths.MCT_DUMP_DIRECTORY);
initSourceFileSelector();
}
});
btnSelectFromMTools.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mSelector.setPathOnLoad(Paths.MTools_PATH);
initSourceFileSelector();
}
});
btnCovert2Bin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
checkSavePath();
if (mSourceFilePath == null) {
showToast(getString(R.string.tisp_select_convert_target));
return;
}
if (mSaveFileName == null || mSavePath == null) {
showToast(getString(R.string.tisp_select_convert_save_path));
return;
}
mType = 0;
presenter.convert2Bin(mSourceFilePath);
}
});
btnCovert2Txt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
checkSavePath();
if (mSourceFilePath == null) {
showToast(getString(R.string.tisp_select_convert_target));
return;
}
if (mSaveFileName == null || mSavePath == null) {
showToast(getString(R.string.tisp_select_convert_save_path));
return;
}
mType = 1;
presenter.convert2Txt(mSourceFilePath);
}
});
txtShowFormatDiffrences.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new AlertDialog.Builder(FormatCovertActivity.this).setTitle("Format distinction")
.setMessage("1.Binary file is a general tag data format, which is the same as\". dump\", and compatible with most software.\n2.The tag data format in text format. is easy to view and can also be used in standard MCT programs.").show();
}
});
}
private void initSelector() {
FilesSelectorDialog.Builder builder = new FilesSelectorDialog.Builder(this);
builder.setTitle(R.string.title_file_select)
.setCancelable(false)
.setCanMultiple(false)
.setPathOnLoad(Paths.DUMP_DIRECTORY);
mSelector = builder.create();
}
private void checkSavePath() {
String path = Commons.getCustomerPath(radioGroupPathSelect);
String name = edtInputSaveName.getText().toString();
if (!StringUtil.isEmpty(name)) {
//非空文件名。检查是否有/字符,有则为非法!
if (name.contains("/")) {
return;
}
//进行最终的拼接!
mSavePath = path;
mSaveFileName = name;
} else {
// FIXME: 2019/5/31 修复空指针闪退!
if (mSourceFilePath != null) {
File file = new File(mSourceFilePath);
mSavePath = file.getParent();
mSaveFileName = file.getName();
}
}
}
private void initSourceFileSelector() {
mSelector.setCanGetPath(false);
mSelector.setOnSelectListener(new FilesSelectorDialog.OnSelectListener() {
@Override
public void selected(File file) {
mSourceFilePath = file.getAbsolutePath();
txtSelectFormAnywhere.setText((getString(R.string.res) + file.getName()));
showToast(getString(R.string.success));
}
});
mSelector.show();
}
@Override
protected void onDestroy() {
//销毁视图绑定!
presenter.detachView();
super.onDestroy();
}
@Override
public void onConvertSucess(byte[] result) {
//判断结果有效性!
if (result == null) {
showToast(getString(R.string.tips_convert_result_null));
return;
}
if (mSavePath == null) {
showToast(getString(R.string.tips_convert_save_path_null));
return;
}
if (mSaveFileName == null) {
showToast(getString(R.string.tips_convert_save_name_null));
return;
}
switch (mType) {
case 0:
presenter.save2BIN(result, mSavePath, mSaveFileName);
break;
case 1:
presenter.save2TXT(result, mSavePath, mSaveFileName);
break;
default:
break;
}
}
@Override
public void onConvertFail(String errorMsg) {
showToast(errorMsg);
}
@Override
public void onSaveSuccess() {
showToast(getString(R.string.success));
}
@Override
public void onSaveFail(String msg) {
if (msg != null)
runOnUiThread(() -> {
showToast(msg);
});
}
@Override
public void showToast(String msg) {
runOnUiThread(() -> {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
});
}
@Override
public void showDialog(String title, String msg) {
}
@Override
public void hideDialog() {
}
}
@@ -90,9 +90,7 @@ public class Proxmark3FirmwareActivity extends BaseActivity implements DevCallba
proDialog1 = new ProDialog1(context);
if (!Commons.isElfDecompressed()) {
Proxmark3Installer.installIfNeed(this, null);
}
Proxmark3Installer.installIfNeed(this, null);
initViews();
initActions();
@@ -4,9 +4,6 @@ import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -21,11 +18,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.termux.app.TermuxService;
import cn.dxl.common.util.AppUtil;
import cn.dxl.common.util.FileUtils;
import cn.dxl.common.util.LogUtils;
import cn.dxl.common.util.RestartUtils;
import cn.rrg.rdv.R;
import cn.rrg.rdv.binder.ItemSingleTextBean;
@@ -41,8 +34,6 @@ import cn.rrg.rdv.util.Proxmark3Installer;
import me.drakeet.multitype.Items;
import me.drakeet.multitype.MultiTypeAdapter;
import static android.app.Activity.RESULT_OK;
/*
* 主设置活动!
* */
@@ -50,9 +41,8 @@ public class MainSettingsFragment
extends BaseFragment {
private RecyclerView rvSettingsList;
private SharedPreferences preferences;
private MultiTypeAdapter multiTypeAdapter;
private Items items = new Items();
private final Items items = new Items();
@Nullable
@Override
@@ -62,7 +52,6 @@ public class MainSettingsFragment
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
preferences = Commons.getPrivatePreferences();
multiTypeAdapter = new MultiTypeAdapter();
initViews(view);
@@ -127,7 +116,7 @@ public class MainSettingsFragment
pm3Res.setMessage(Commons.isPM3ResInitialled() ? getString(R.string.initialized) : getString(R.string.uninitialized));
items.add(pm3Res);
// 只有SDK版本大于等于24的时候才使能PM3的高级视图
// PM3 Full terminal only run on sdk > 23
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
ItemToggleBean pm3AutoGo = new ItemToggleBean(getString(R.string.title_pm3_autogo_setting)) {
@@ -192,32 +181,6 @@ public class MainSettingsFragment
multiTypeAdapter.notifyDataSetChanged();
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 0x77 && resultCode == RESULT_OK && data != null) {
Uri uri = data.getData();
if (uri != null) {
// get file path
String path = FileUtils.getFilePathByUri(uri);
// save
LogUtils.d("获取到的路径: " + path);
}
}
}
public static String getVersion(Context context) {
if (context == null) return "unknown";
try {
PackageInfo pi = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
return pi.versionName;
} catch (PackageManager.NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return context.getString(R.string.unknown);
}
}
private String languageTran() {
String currentLanguage = Commons.getLanguage();
@@ -12,13 +12,9 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import com.proxgrind.pm3flasher.Proxmark3Flasher;
import cn.rrg.rdv.R;
import cn.rrg.rdv.activities.tools.DumpEqualActivity;
import cn.rrg.rdv.activities.tools.DumpListActivity;
import cn.rrg.rdv.activities.tools.FileListActivity;
import cn.rrg.rdv.activities.tools.FormatCovertActivity;
import cn.rrg.rdv.activities.tools.KeyFileListActivity;
import cn.rrg.rdv.activities.tools.Proxmark3FirmwareActivity;
import cn.rrg.rdv.fragment.base.BaseFragment;
@@ -28,8 +24,6 @@ public class ToolsAccessFragment
private Button btnDataEditor = null;
private Button btnKeyEditor = null;
private Button btnFormatCovert = null;
private Button btnDiffTools = null;
private Button btnPM3Flasher;
@Nullable
@@ -49,8 +43,6 @@ public class ToolsAccessFragment
private void initViews(View view) {
btnDataEditor = view.findViewById(R.id.btnDumpEditor);
btnKeyEditor = view.findViewById(R.id.btnKeyEditor);
btnFormatCovert = view.findViewById(R.id.btnConvertFormat);
btnDiffTools = view.findViewById(R.id.btnDiffTool);
btnPM3Flasher = view.findViewById(R.id.btnPM3Flasher);
}
@@ -59,10 +51,6 @@ public class ToolsAccessFragment
startActivity(new Intent(context, DumpListActivity.class).putExtra("mode", DumpListActivity.MODE.EDIT));
});
btnDiffTools.setOnClickListener(v -> startActivity(new Intent(context, DumpEqualActivity.class)));
btnFormatCovert.setOnClickListener(v -> startActivity(new Intent(context, FormatCovertActivity.class)));
btnKeyEditor.setOnClickListener(v -> startActivity(
new Intent(context, KeyFileListActivity.class).putExtra("mode", FileListActivity.MODE.EDIT))
);
@@ -39,18 +39,6 @@ public class Commons {
private Commons() {
}
//呼叫QQ
public static void callQQ(Context context, String qq, Runnable onFaild) {
//这里的228451878是自己指定的QQ号码,可以自己更换
String url = "mqqwpa://im/chat?chat_type=wpa&uin=" + qq;
try {
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
} catch (Exception e) {
onFaild.run();
}
}
//打开浏览器,链接到指定的链接
public static void openUrl(Context context, String url) {
try {
Uri uri = Uri.parse(url);
@@ -63,32 +51,9 @@ public class Commons {
}
}
//根据单选返回地址!
public static String getCustomerPath(RadioGroup group) {
if (group == null) return Paths.DUMP_DIRECTORY;
int id = group.getCheckedRadioButtonId();
String path;
if (id == R.id.rdoBtnWriteDataDefaultPath) {
path = Paths.DUMP_DIRECTORY;
} else if (id == R.id.rdoBtnWriteDataMCTPath) {
path = Paths.MCT_DUMP_DIRECTORY;
} else if (id == R.id.rdoBtnWriteDataWecatPath) {
path = Paths.WECAT_DIRECTORY;
} else if (id == R.id.rdoBtnWriteDataSdcardPath) {
path = Paths.EXTERNAL_STORAGE_DIRECTORY;
} else if (id == R.id.rdoBtnWriteDataQQPath) {
path = Paths.QQ_DIRECTORY;
} else if (id == R.id.rdoBtnWriteDataMToolsPath) {
return Paths.MTools_DUMP_DIRECTORY;
} else if (id == R.id.rdoBtnWriteDataPM3Path) {
return Paths.PM3_DIRECTORY;
} else {
path = Paths.DUMP_DIRECTORY;
}
return path;
}
//移除设备对象从集合中!
/**
* Remove the device from a list
*/
public static boolean removeDevByList(DevBean devBean, List<DevBean> list) {
if (devBean != null) {
String addr = devBean.getMacAddress();
@@ -107,14 +72,18 @@ public class Commons {
return true;
}
//判断两个设备是否是一致的
/**
* Check device is equal
*/
public static boolean equalDebBean(DevBean a, DevBean b) {
if (a == b) return true;
if (a == null || b == null) return false;
return a.getMacAddress().equals(b.getMacAddress());
}
//从蓝牙适配器中取出历史连接的设备列表!
/**
* Get all device from bluetooth adapter
*/
public static DevBean[] getDevsFromBTAdapter(BluetoothAdapter btAdapter) {
ArrayList<DevBean> devList = new ArrayList<>();
Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices();
@@ -131,10 +100,12 @@ public class Commons {
return ArrayUtils.list2Arr(devList);
}
//设备是否是USB设备!
/**
* Check is a usb device
* the usb no valid mac!
*/
public static boolean isUsbDevice(String address) {
if (address == null) return false;
//这三种mac是开发者定义的用于区分USB设备和蓝牙设备的特征符!
switch (address) {
case "00:00:00:00:00:00":
case "00:00:00:00:00:01":
@@ -20,16 +20,15 @@ public class InitUtil {
public static final String LOG_TAG = InitUtil.class.getSimpleName();
public static void initApplicationResource(Context context) {
AssetsUtil au = new AssetsUtil(context);
File dump_dir = new File(Paths.DUMP_DIRECTORY);
if (!dump_dir.exists()) {
if (!dump_dir.mkdirs()) {
Log.d(LOG_TAG, "init dumps dir fail!");
} else {
initDumpFile(au);
initDumpFile(context);
}
} else {
initDumpFile(au);
initDumpFile(context);
}
File driver_dir = new File(Paths.DRIVER_DIRECTORY);
if (!driver_dir.exists()) {
@@ -42,20 +41,20 @@ public class InitUtil {
if (!keys_dir.mkdirs()) {
Log.d(LOG_TAG, "init keys dir fail!");
} else {
initKeysFile(au);
initKeysFile(context);
}
} else {
initKeysFile(au);
initKeysFile(context);
}
File common_dir = new File(Paths.COMMON_DIRECTORY);
if (!common_dir.exists()) {
if (common_dir.mkdirs()) {
initCommonInFile();
initMfInfoMapsFile(au);
initMfInfoMapsFile(context);
}
} else {
initCommonInFile();
initMfInfoMapsFile(au);
initMfInfoMapsFile(context);
}
File pn53x_dir = new File(Paths.PN53X_DIRRECTORY);
if (!pn53x_dir.exists()) {
@@ -71,11 +70,11 @@ public class InitUtil {
if (!pm3_dir.mkdirs()) {
Log.d(LOG_TAG, "init pm3 dir fail!");
} else {
initEasyButtonFile(au);
initEasyButtonFile(context);
initPM3ForwardFile();
}
} else {
initEasyButtonFile(au);
initEasyButtonFile(context);
initPM3ForwardFile();
}
Commons.updatePM3Cwd();
@@ -95,45 +94,45 @@ public class InitUtil {
}
}
private static void initMfInfoMapsFile(AssetsUtil au) {
private static void initMfInfoMapsFile(Context context) {
File f1 = new File(Paths.COMMON_DIRECTORY + "/" + "template_mifare_info_en.html");
File f2 = new File(Paths.COMMON_DIRECTORY + "/" + "template_tag_info_en.html");
//移动两个标签信息HTML文件到指定目录!
au.copyFile("template_mifare_info_en.html",
AssetsUtil.copyFile(context, "template_mifare_info_en.html",
new File(Paths.COMMON_DIRECTORY + "/" + "template_mifare_info_en.html").getAbsolutePath());
au.copyFile("template_tag_info_en.html",
AssetsUtil.copyFile(context, "template_tag_info_en.html",
new File(Paths.COMMON_DIRECTORY + "/" + "template_tag_info_en.html").getAbsolutePath());
}
private static void initDumpFile(AssetsUtil au) {
private static void initDumpFile(Context context) {
File target = new File(Paths.DEFAULT_DUMP_FILE);
//目标文件夹里是否有这个文件!
if (!(target.exists() && target.isFile())) {
//包里面是否有这个资源文件!
if (au.copyFile(Paths.DEFAULT_DUMP_NAME, Paths.DEFAULT_DUMP_FILE)) {
if (AssetsUtil.copyFile(context, Paths.DEFAULT_DUMP_NAME, Paths.DEFAULT_DUMP_FILE)) {
Log.d(LOG_TAG, "创建默认的空白数据文件成功!");
}
}
}
private static void initKeysFile(AssetsUtil au) {
private static void initKeysFile(Context context) {
File target = new File(Paths.DEFAULT_KEYS_FILE);
//目标文件夹里是否有这个文件!
if (!(target.exists() && target.isFile())) {
//包里面是否有这个资源文件!
if (au.copyFile(Paths.DEFAULT_KEYS_NAME, Paths.DEFAULT_KEYS_FILE)) {
if (AssetsUtil.copyFile(context, Paths.DEFAULT_KEYS_NAME, Paths.DEFAULT_KEYS_FILE)) {
Log.d(LOG_TAG, "创建默认的空白数据文件成功!");
}
}
}
private static void initEasyButtonFile(AssetsUtil au) {
private static void initEasyButtonFile(Context context) {
File target = new File(Paths.PM3_CMD_FILE);
//目标文件夹里是否有这个文件!
if (!(target.exists() && target.isFile())) {
//包里面是否有这个资源文件!
if (au.copyFile(Paths.DEFAULT_CMD_NAME, Paths.PM3_CMD_FILE)) {
if (AssetsUtil.copyFile(context, Paths.DEFAULT_CMD_NAME, Paths.PM3_CMD_FILE)) {
Log.d(LOG_TAG, "创建默认的动态按钮文件成功!");
}
}
@@ -3,15 +3,45 @@ package cn.rrg.rdv.util;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import com.termux.app.TermuxService;
import java.io.File;
import cn.dxl.common.util.AssetsUtil;
import cn.dxl.common.util.FileUtils;
import cn.dxl.common.util.LogUtils;
import cn.rrg.rdv.R;
public class Proxmark3Installer {
static String zipName = "proxmark3.zip";
static String verName = "pm3_version.txt";
static String zipFile = TermuxService.HOME_PATH + File.separator + zipName;
static String verFile = TermuxService.HOME_PATH + File.separator + verName;
public static boolean isCanInstall(Context context) {
try {
String version_assets = AssetsUtil.readLines(context, verName);
// read version for res installed
String version_installed = FileUtils.readLine(new File(verFile));
// check version
if (version_installed.length() == 0) {
// no file found or file have some problem, we need reinstall
return true;
}
if (version_installed.equals(version_assets)) {
// if version same, we can stop install
LogUtils.d("Proxmark3Installer->installIfNeed(): version same, we can stop install.");
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* Install the pm3 client and resource if need!
@@ -29,10 +59,23 @@ public class Proxmark3Installer {
new Thread(new Runnable() {
@Override
public void run() {
String zipName = "proxmark3.zip";
String zipFile = TermuxService.HOME_PATH + File.separator + zipName;
new AssetsUtil(activity).copyFile(zipName, zipFile);
try {
if (!isCanInstall(activity)) {
if (whenDone != null) activity.runOnUiThread(whenDone);
progress.cancel();
return;
}
// before install, we need delete all old res
FileUtils.delete(new File(TermuxService.HOME_PATH));
// and recreate path
FileUtils.createPaths(new File(TermuxService.HOME_PATH));
// copy zip file from apk to local
AssetsUtil.copyFile(activity, zipName, zipFile);
AssetsUtil.copyFile(activity, verName, verFile);
// unzip to home path
ZipUtils.UnZipFolder(zipFile, TermuxService.HOME_PATH, new ZipUtils.Progress() {
@Override
public void onProgress(int max, int current, String file) {
@@ -45,37 +88,49 @@ public class Proxmark3Installer {
});
}
});
LogUtils.d("PM3 Resource install finish.");
} catch (Exception e) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
new AlertDialog.Builder(activity)
.setTitle(R.string.error)
.setMessage(e.getMessage())
.show();
activity.runOnUiThread(() -> {
try {
progress.dismiss();
} catch (RuntimeException e) {
// Activity already dismissed - ignore.
}
});
if (whenDone != null)
whenDone.run();
}
});
showDialogOnErr(activity, progress, e.getMessage(), whenDone);
e.printStackTrace();
}
showDialogOnOk(activity, progress);
if (whenDone != null) activity.runOnUiThread(whenDone);
}
}).start();
}
// show dialog if task execute success
public static void showDialogOnOk(Activity activity, ProgressDialog dialog) {
activity.runOnUiThread(() -> {
try {
dialog.dismiss();
} catch (RuntimeException e) {
// Activity already dismissed - ignore.
}
});
}
// show dialog if has err
public static void showDialogOnErr(Activity activity, ProgressDialog dialog, String errMsg, Runnable call) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
new AlertDialog.Builder(activity)
.setTitle(R.string.error)
.setMessage(errMsg)
.show();
activity.runOnUiThread(() -> {
try {
progress.dismiss();
dialog.dismiss();
} catch (RuntimeException e) {
// Activity already dismissed - ignore.
}
});
if (whenDone != null)
activity.runOnUiThread(whenDone);
if (call != null)
call.run();
}
}).start();
});
}
}
@@ -1,12 +1,13 @@
package cn.rrg.rdv.util;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
@@ -14,6 +15,8 @@ import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import cn.dxl.common.util.LogUtils;
/**
* @author: lijuan
* @description: 解压ZIP文件
@@ -225,4 +228,32 @@ public class ZipUtils {
inZip.close();
return fileList;
}
/**
* @author dxl
* read a file from zip file(no unzip)
*/
public static String readZipFile(File zipFile, String readFileName) throws Exception {
ZipFile zf = new ZipFile(zipFile);
InputStream in = new BufferedInputStream(new FileInputStream(zipFile));
ZipInputStream zin = new ZipInputStream(in);
ZipEntry ze;
StringBuilder sb = new StringBuilder();
String line;
while ((ze = zin.getNextEntry()) != null) {
LogUtils.d("项目名: " + ze.getName());
if (!ze.isDirectory()) {
if (ze.getName().contains(readFileName)) {
BufferedReader br = new BufferedReader(new InputStreamReader(zf.getInputStream(ze)));
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
}
}
}
zin.closeEntry();
in.close();
return sb.toString();
}
}
@@ -72,149 +72,4 @@
android:gravity="center"
android:padding="6dp" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="28dp"
android:background="@color/md_grey_100"
android:visibility="gone">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/main_settings"
android:drawablePadding="16dp"
android:gravity="start"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="@string/appSettings" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/md_grey_300" />
<TextView
android:id="@+id/txtUserHelp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/help_blue"
android:drawablePadding="16dp"
android:gravity="start"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="@string/usage" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/md_grey_300"
android:visibility="gone" />
<TextView
android:id="@+id/txtDisclaimer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/disclaimer_blue"
android:drawablePadding="16dp"
android:gravity="start"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="@string/disclaimer" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/md_grey_300" />
<TextView
android:id="@+id/txtJoinQQGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/qq_group_blue"
android:drawablePadding="16dp"
android:gravity="start"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="@string/joinGroup" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/md_grey_300" />
<TextView
android:id="@+id/txtContactDev"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/dev_blue"
android:drawablePadding="16dp"
android:gravity="start"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="@string/contactDev" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/md_grey_300" />
<TextView
android:id="@+id/txtSendLogFile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/share"
android:drawablePadding="16dp"
android:gravity="start"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="@string/sendLog" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/md_grey_300" />
<TextView
android:id="@+id/txtCleanData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/clear_blue"
android:drawablePadding="16dp"
android:gravity="start"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="@string/clearData" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/md_grey_300" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/update_blue"
android:drawablePadding="16dp"
android:gravity="start"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="@string/checkUpdate" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/md_grey_300" />
</LinearLayout>
</ScrollView>
</LinearLayout>
@@ -79,149 +79,4 @@
</ScrollView>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="28dp"
android:background="@color/md_grey_100"
android:visibility="gone">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/main_settings"
android:drawablePadding="16dp"
android:gravity="start"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="@string/appSettings" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/md_grey_300" />
<TextView
android:id="@+id/txtUserHelp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/help_blue"
android:drawablePadding="16dp"
android:gravity="start"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="@string/usage" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/md_grey_300"
android:visibility="gone" />
<TextView
android:id="@+id/txtDisclaimer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/disclaimer_blue"
android:drawablePadding="16dp"
android:gravity="start"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="@string/disclaimer" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/md_grey_300" />
<TextView
android:id="@+id/txtJoinQQGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/qq_group_blue"
android:drawablePadding="16dp"
android:gravity="start"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="@string/joinGroup" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/md_grey_300" />
<TextView
android:id="@+id/txtContactDev"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/dev_blue"
android:drawablePadding="16dp"
android:gravity="start"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="@string/contactDev" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/md_grey_300" />
<TextView
android:id="@+id/txtSendLogFile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/share"
android:drawablePadding="16dp"
android:gravity="start"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="@string/sendLog" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/md_grey_300" />
<TextView
android:id="@+id/txtCleanData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/clear_blue"
android:drawablePadding="16dp"
android:gravity="start"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="@string/clearData" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/md_grey_300" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableStart="@drawable/update_blue"
android:drawablePadding="16dp"
android:gravity="start"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="@string/checkUpdate" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/md_grey_300" />
</LinearLayout>
</ScrollView>
</RelativeLayout>
@@ -63,52 +63,6 @@
android:text="@string/title_pm3_firmware_flasher"
android:textAllCaps="false" />
<Button
android:id="@+id/btnDiffTool"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@drawable/btn_selectot_white"
android:gravity="start|center"
android:paddingStart="16dp"
android:paddingTop="8dp"
android:paddingEnd="16dp"
android:paddingBottom="8dp"
android:text="@string/data_diff"
android:textAllCaps="false"
android:visibility="gone" />
<Button
android:id="@+id/btnUnionKeyEditor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@drawable/btn_selectot_white"
android:drawableEnd="@drawable/main_union_key"
android:gravity="start|center"
android:paddingStart="16dp"
android:paddingTop="8dp"
android:paddingEnd="16dp"
android:paddingBottom="8dp"
android:text="@string/union_keys"
android:textAllCaps="false"
android:visibility="gone" />
<Button
android:id="@+id/btnConvertFormat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@drawable/btn_selectot_white"
android:gravity="start|center"
android:paddingStart="16dp"
android:paddingTop="8dp"
android:paddingEnd="16dp"
android:paddingBottom="8dp"
android:text="@string/format_covert"
android:textAllCaps="false"
android:visibility="gone" />
</LinearLayout>
</ScrollView>

Some files were not shown because too many files have changed in this diff Show More