环境
android 8.1 rk3128
思考
1.往android framework 中添加自己的布局需要改什么地方怎么改?
2.直接加上去会遇到什么问题?
我开始是直接在android studio中写好布局文件,完了把xml文件直接拷贝到framewock的资源xml文件夹,编译报错,看提示去改,看提示不懂的就随便打开一个xml文件找一个布局view id查找整个framework,一步步下来,就知道要改什么地方。这样是最笨也是最简单有效的,本文记录后面再有这样需求就可以直接照着改了
源码
布局 文件layout_dialog_report.xml
// An highlighted block
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+android:id/tv"
android:layout_width="match_parent"
android:text="Bitte berechnen Sie das Ergebnis der folgenden mathematischen Formel zur Überprüfung"
android:layout_margin="16dp"
android:textSize="25sp"
android:textColor="@android:color/black"
android:visibility="gone"
android:layout_height="wrap_content"/>
<TextView
android:id="@+android:id/vs_tv_number"
android:layout_width="match_parent"
android:text="19 * 23 = ?"
android:layout_margin="16dp"
android:textSize="30sp"
android:layout_height="35dp"/>
<EditText
android:id="@+android:id/vs_et_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:inputType="text"/>
</LinearLayout>
以上布局代码跟普通apk唯一有区别就是id,普通apk是@+id/
往framework里加普通apk的布局,只需把普通布局的改成@+android:id/即可。然后把布局文件拷贝到framework/base/core/res/res/xml/(xml是我自己要拷到这个目录,也可以拷到layout目录)
到这之后还需要改几个地方:framework/base/core/res/res/value/目录下的symbols.xml,public.xml和ids.xml。
symbols.xml —是把布局文件名写入
<java-symbol type="xml" name="layout_dialog_report" />
ids.xml —是把布局里的控件写入
<item type="id" name="vs_tv_number" />
<item type="id" name="vs_et_input" />
public.xml —是把控件id指定(type id是0x010200开头)
<public type="id" name="vs_tv_number" id="0x0102009b" />
<public type="id" name="vs_et_input" id="0x0102009c" />
id如果不是0x010200就编译报错 如下:
error: trying to add resource 'id/vs_et_input' with ID 0x0104001c but type 'id' already has ID 2
看这个错误提示 ID 2 适用于id type,不能再把id type指定到 ID 4(string type的引用)
java代码调用
// An highlighted block
private void checkResult() {
Random random = new Random(System.currentTimeMillis());
View inputView = LayoutInflater.from(ActivityThread.currentActivityThread().getSystemUiContext()).inflate(com.android.internal.R.xml.layout_dialog_report, null);
final TextView tv = inputView.findViewById(com.android.internal.R.id.vs_tv_number);
final EditText et = inputView.findViewById(com.android.internal.R.id.vs_et_input);
final int x = random.nextInt(100);
final int y = random.nextInt(100);
final int operationalRules = random.nextInt(4);
switch (operationalRules) {
case 0:
tv.setText(x + " + " + y + " = ?");
break;
case 1:
tv.setText(x + " - " + y + " = ?");
break;
case 2:
tv.setText(x + " * " + y + " = ?");
break;
case 3:
tv.setText(x + " / " + y + " = ?");
break;
}
AlertDialog.Builder n = new AlertDialog.Builder(ActivityThread.currentActivityThread().getSystemUiContext());
n.setTitle("Bitte berechnen Sie das Ergebnis der folgenden mathematischen Formel zur Überprüfung");
n.setView(inputView); // 设置显示的view
n.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String str = et.getText().toString();
if(str == null){
tv.setText("Falsche Eingabe");
try {
Thread.sleep(3000);
}catch (Exception e){
e.printStackTrace();
}
dialog.dismiss();
return;
}
String regEx="[^0-9]";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(str);
String num = m.replaceAll("").trim();
int i = Integer.parseInt(num);
int result = 0;
switch (operationalRules) {
case 0:
result = x + y;
break;
case 1:
result = x - y;
break;
case 2:
result = x * y;
break;
case 3:
if (y == 0) {
result = x * y;
break;
}
result = x / y;
break;
}
android.util.Log.i("alan_vs","i="+i+"result ="+result);
if (i == result) {
jiachang = false;
android.util.Log.i("alan_vs","checkResult 1"+jiachang);
dialog.dismiss();
} else {
jiachang = true;
}
}
});
n.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
jiachang = true;
}
});
AlertDialog dialog = n.create();
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
dialog.show();
}
调用和编译注意(这里是遇到的问题和解决)
在PhonewindowManager里面调用记得用Handler, Unable to add window – token null is not valid; is your activity running?–需要dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);解决,布局文件新增修改的源码需要更新api,因此需要make update-api编译api更新