http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0717/3196.html
使用AndroidStudio一分钟实现Navigation Drawer 导航抽屉效果
https://blog.csdn.net/finddreams/article/details/49492579
定制自己的Log日志工具
https://blog.csdn.net/guolipeng_network/article/details/73111418
使用Intent传递自定义对象
https://blog.csdn.net/mq2856992713/article/details/51049617
1.实现Serializable接口的对象
2.实现Parcelable接口的对象
创建定时任务
1.Java Timer类
2.Android Alarm机制
Alarm可以在需要进行定时任务时唤醒CPUhttps://blog.csdn.net/u014492609/article/details/51475254
AndroidStudio断点调试
https://blog.csdn.net/qq_32452623/article/details/53769708
https://blog.csdn.net/huangxiaominglipeng/article/details/53100811
APK签名
http://192.168.3.77:8989/wcp/webdoc/view/Pub402880cd5dc4c831015dd0c28455015f.html
http://192.168.3.77:8989/wcp/webdoc/view/Pub402880cd5c5da6e7015d5f2cf2c30c12.html
O平台签名有问题,试了M平台和N平台的方法都不行。所以选择了模块编译。18.内置的apk 如何实现签名 获取系统权限
查看签名信息 keytool -printcert -file
[FAQ00366] 如何使Android应用程序获取系统权限
在已经编译好的工程中 :out/host/linux-x86/framework/signapk.jar 取出 signapk.jar 文件 ,然后从 build/target/product/security/项目名字/ 下面取出另外两个文件 platform.x509.pem 和 platform.pk8
然后三个文件+apk文件,同一个路径下。 执行签名操作
java -jar signapk.jar platform.x509.pem platform.pk8 input.apk output.apk
然后apk就相当于签名,获取了系统权限。。当然,名字实际上也重新命名了。L–>alps/device/mediatek/common/security/项目
检查APK签名是否为platform签名:
jarsigner -verify -verbose -certs ${your_apk}>log.txt
./aapt dump badging Maps.apk > log2.txt
keytool -list -v -keystore IDG.JKS
签名前需先删除原始apk中的META-INF
jarsigner -verbose -keystore IDG.JKS -signedjar IDG_CodeTelMessenger.apk IDG_CodeTelMessenger.apk viewappkey
jarsigner -verbose -keystore CERT.RSA -signedjar momkntestapp-sign.apk -digestalg SHA1 -sigalg SHA1withRSA momkntestapp.apk momkn_calib 添加算法jdk1.7以后
keytool -printcert -file MOMKN_CA.RSA/home/rwd/workspace/momkntestapp/bin/momkntestapp-eclipse.apk
第一步生成keystore 用来签名
keytool -genkey -v -keystore android.keystore -alias android.keystore -keyalg RSA -validity 3650
第二步生成 .cer文件 放到代码里面
keytool -export -alias android.keystore -file android.cer -keystore android.keystoregyn@gyn-ThinkStation-P300:~$ keytool -genkey -v -keystore piranha -alias piranha -keyalg RSA -keysize 2048 -validity 7300
Enter keystore password:
Re-enter new password:
What is your first and last name?
[Unknown]: boloro
What is the name of your organizational unit?
[Unknown]: sagereal
What is the name of your organization?
[Unknown]: sagereal
What is the name of your City or Locality?
[Unknown]: ningbo
What is the name of your State or Province?
[Unknown]: zhejiang
What is the two-letter country code for this unit?
[Unknown]: cn
Is CN=boloro, OU=sagereal, O=sagereal, L=ningbo, ST=zhejiang, C=cn correct?
[no]: yGenerating 2,048 bit RSA key pair and self-signed certificate (SHA256withRSA) with a validity of 7,300 days
for: CN=boloro, OU=sagereal, O=sagereal, L=ningbo, ST=zhejiang, C=cn
Enter key password for <android.keystore>
(RETURN if same as keystore password):
Re-enter new password:
[Storing android.keystore]
gyn@gyn-ThinkStation-P300:~$ keytool -export -alias android.keystore -file android.cer -keystore android.keystore
Enter keystore password:
Certificate stored in filejarsigner -verbose -keystore com.bjw.ComAssistant_2.keystore -signedjar com.bjw.ComAssistant_2_signed.apk -digestalg SHA1 -sigalg MD5withRSA com.bjw.ComAssistant_2.apk android.keystore
jarsigner命令格式:-verbose输出详细信息 -keystore密钥库位置 -signedjar要生成的文件 要签名的文件 密钥库文件
-signedjar PhoneBook_signed.apk表示签名后生成的APK名称
PhoneBook.apk表示未签名的APK
Android软件-digestalg SHA1 -sigalg MD5withRSA:这就是必须加上的参数,如果你是jdk 1.6也不受影响
-androiddebugkey表示Key的别名
AppUpdate添加到Settings一级目录
参照Software #119639 (Closed): [传音需求]手机内部User Guide!
修改preference
1先通过DDMS查看是哪个Activity
2这个Activity继承了PreferenceActivity,重写了preference的一系列方法通过控件的id或字符串找到preference的布局文件(这里可能找到很多preference,看哪个preference和Activity相似或者preference的布局和手机是对应的)。
再查看哪个java文件调用了这xml文件,grep会发现: Xxx.java: addPreferencesFromResource(R.xml.preference_display_options);
在该Java文件的onCreate()方法中获取Preference,findPreference by key,setTitle()
final Preference aboutPreference = findPreference("about");
//chenghao add begin
String str_pre=aboutPreference.getTitle().toString();
String str_convert = str_pre.substring(0, 1).toUpperCase().concat(str_pre.substring(1).toLowerCase());
android.util.Log.e("chenghao666","str_pre="+str_pre);
android.util.Log.e("chenghao666","str_convert="+str_convert);
aboutPreference.setTitle(str_convert);
//chenghao add end
确定具体preference的,找到具体某个preference的key。在Activity中会根据key找到preference,进行一系列操作。
添加全局变量宏开关的三种方式
https://blog.csdn.net/hfreeman2008/article/details/49885885
Redmine115852 wangyannan add autoreboot test function begin
Android各种获取Context方法
https://www.cnblogs.com/chenxibobo/p/6136693.htmlhttps://blog.csdn.net/lmj623565791/article/details/40481055/
张鸿洋https://blog.csdn.net/zy_style/article/details/53230303
基于张鸿洋,做了添加。XXXActivity.this和getApplicationContext的区别呢?
XXXActivity和getApplicationContext返回的肯定不是一个对象,一个是当前Activity的实例,一个是项目的Application的实例。重点看Activity和Application,凡是跟UI相关的,都应该使用Activity做为Context来处理;其他的一些操作,Service,Activity,Application等实例都可以。
也即:
在绝大多数场景下,Activity、Service和Application这三种类型的Context都是可以通用的。
不过有几种场景比较特殊,比如start an Activity,show a Dialog,Layout Inflation。应该使用Activity做为Context来处理!如何获取Context:
1:View.getContext,返回当前View对象的Context对象,通常是当前正在展示的Activity对象。2:Activity.getApplicationContext,获取当前Activity所在的(应用)进程的Context对象,通常我们使用Context对象时,要优先考虑这个全局的进程Context。
3:ContextWrapper.getBaseContext():用来获取一个ContextWrapper进行装饰之前的Context,可以使用这个方法,这个方法在实际开发中使用并不多,也不建议使用。
4:Activity.this 返回当前的Activity实例,如果是UI控件需要使用Activity作为Context对象,但是默认的Toast实际上使用ApplicationContext也可以。
1. getApplicationContext()
这个函数返回的这个Application的上下文,所以是与app挂钩的,所以在整个生命周期里面都是不变的,这个好理解,但是使用的时候要注意,该context是和引用的生命周期一致的,所以和activity生命周期挂钩的任务不要使用该context,比如网络访问,防止内存泄露
2. getBasecontext():
不推荐使用
3. getApplication():
getApplication只能被Activity和Services使用,
4. getParent() :
返回activity的上下文,如果这个子视图的话,换句话说,就是当在子视图里面调用的话就返回一个带有子视图的activity对象,一目了然。
5.getActivity():
在fragment中使用,返回该fragment所依附的activity上下文
6.this
ComponentName
https://blog.csdn.net/huangyabin001/article/details/36626341ComponentName这个类主要用来定义可见一个应用程序组件,例如:Activity,Service,BroadcastReceiver或者ContentProvider。
那么,如何用ComponentName来定义一个组件呢。
ComponentName的构造函数:ComponentName(String pkg,String cls)
omponentName来封装一个组件的应用包名和组件的名字。
在Android中组件之间的交流往往使用意图(Intent)来完成的,那么在Intent中有一个方法可以封装一个ComponentName,最后我们在使用意图去完成我们需要实现的功能。
例子:
ComponentName cn=new ComponentName("com.example.appreceiver", "com.example.appreceiver.MainActivity");
Intent intent = new Intent();
intent.setComponent(cn);
startActivityForResult(intent, 2);
问题一:
Android service如何获取调用者的真实package name?
我有一个service,别的App可以调用它。
我的service想获取调用者的packageName,该如何做呢?
实践表明:必须调用者事先写进Intent, 才能才能通过intent.getComponent().getPackageName()获取到包名。
但是如何才能不用调用者事先写入,直接获取(即,如何防止用户伪造packageName)?
回答:
String callingApp = context.getPackageManager().getNameForUid(Binder.getCallingUid());
或者 AppGlobals.getPackageManager().getNameForUid(Binder.getCallingUid());获取调用者的类名:
intent.getComponent().getClassName();问题二:
Launcher加载所有的已安装的程序的列表,当点击图标时可以启动另一个应用。
https://blog.csdn.net/u012532559/article/details/52766348
我们一般都不知道应用程序的启动Activity的类名,而只知道包名,我们可以通过ResolveInfo类来取得启动Acitivty的类名。
private void openApp(String packageName) {
PackageInfo pi = getPackageManager().getPackageInfo(packageName, 0);
Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
resolveIntent.setPackage(pi.packageName);
List<ResolveInfo> apps = pm.queryIntentActivities(resolveIntent, 0);
ResolveInfo ri = apps.iterator().next();
if (ri != null ) {
String packageName = ri.activityInfo.packageName;
String className = ri.activityInfo.name;
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName cn = new ComponentName(packageName, className);
intent.setComponent(cn);
startActivity(intent);
}
}
单例模式
与Context相关 Context的保持
单例模式:是一种常用的软件设计模式,在它的核心结构中值包含一个被称为单例的特殊类。一个类只有一个实例,即一个类只有一个对象实例。
对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;售票时,一共有100张票,可有有多个窗口同时售票,但需要保证不要超售(这里的票数余量就是单例,售票涉及到多线程)。如果不是用机制对窗口对象进行唯一化将弹出多个窗口,如果这些窗口显示的都是相同的内容,重复创建就会浪费资源。内存泄露:
Java中的内存泄露,广义并通俗的说,就是:不再会被使用的对象的内存不能被回收,就是内存泄露。
如果长生命周期的对象持有短生命周期的引用,就很可能会出现内存泄露。
编写工具类时,可能会编写成单例的方式,这些工具类大多需要去访问资源,也就说需要Context的参与。
单例中内部保持了一个Context的引用,不能确定传入的Context是哪种。可能会造成内存泄露。你在某个Activity里面为了方便,直接传了个this;这样问题就来了,我们的这个类中的sInstance是一个static且强引用的,在其内部引用了一个Activity作为Context,也就是说,我们的这个Activity只要我们的项目活着,就没有办法进行内存回收。而我们的Activity的生命周期肯定没这么长,所以造成了内存泄漏。
那么,我们如何才能避免这样的问题呢?
将context引用改为ApplicationContext,它的生命周期和我们的单例对象一致。就不会造成内存泄露了。
单例模式例子:
package com.mooc.shader.roundimageview;
import android.content.Context;
public class CustomManager
{
private static CustomManager sInstance;
private Context mContext;
private CustomManager(Context context)
{
this.mContext = context;
}
public static synchronized CustomManager getInstance(Context context)
{
if (sInstance == null)
{
sInstance = new CustomManager(context);//context不确定是哪种,可能是Activity。需要修改成context.getApplicationContext()
}
return sInstance;
}
//some methods
private void someOtherMethodNeedContext()
{
}
}
2018-04-14-(使用Github及Git常见命令)
第一次使用github
执行git clone命令:chenghao@chenghao-ThinkStation-P300:~/Project/github-android/Test$ git clone git@github.com:Cheng8Hao/hello_world.git
正克隆到 'hello_world'…
The authenticity of host 'github.com (192.30.253.112)' can't be established.
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,192.30.253.112' (RSA) to the list of known hosts.
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 7 (delta 0), reused 0 (delta 0), pack-reused 0
接收对象中: 100% (7/7), done.
检查连接… 完成。
chenghao@chenghao-ThinkStation-P300:~/Project/github-android/Test$问题:add前取消对某文件的修改
git checkout问题一: git add 添加了多余文件怎么撤销添加的操作?
git status 先看一下add 中的文件
git reset HEAD 如果后面什么都不跟的话 就是上一次add 里面的全部撤销了
git reset HEAD XXX/XXX/XXX.java 就是对某个文件进行撤销了
reset只是撤销了添加,文件还是已修改状态,再用checker命令。问题二:
如果不小心弄错了git add后,又git commit了,但是还没有push,怎么办?
git log 查看节点
git reset commit_id (回退到上一个提交的commit_id节点 代码还是原来你修改过后的)
或者git reset –hard commit_id (回退到上一个提交的commit_id节点, 代码的修改也被清除了)问题三:
弄错了git add后,又git commit了,又push了,怎么办?
使用 git revert命令
此次操作之前和之后的commit和history都会保留,并且把这次撤销作为一次最新的提交
git revert HEAD 撤销前一次 commit
git revert HEAD^ 撤销前前一次 commit
git revert commit-id (撤销指定的版本,撤销也会作为一次提交进行保存)
git revert是提交一个新的版本,将需要revert的版本的内容再反向修改回去,版本会递增,不影响之前提交的内容。查看用户名和邮箱地址:
$ git config user.name
$ git config user.emailgit add -A 和 git add . 的区别:
git add -A和 git add . git add -u在功能上看似很相近,但还是存在一点差别
git add . :他会监控工作区的状态树,使用它会把工作时的所有变化提交到暂存区,包括文件内容修改(modified)以及新文件(new),但不包括被删除的文件。
git add -u :他仅监控已经被add的文件(即tracked file),他会将被修改的文件提交到暂存区。add -u 不会提交新文件(untracked file)。(git add –update的缩写)
git add -A :是上面两个功能的合集(git add –all的缩写)https://github.com/I18N486/coolweather
git diff commit-id1 commit-id2 –stat
这个指令可以看两个版本之间有哪些文件改动git log -p file
可以看到具体一个文件的历史改动记录git show
@BindView(R2.id.button)
Button button =(B)fin@BindView(R2.id.button2)
Settings
8.0Settings
https://blog.csdn.net/qq_31012033/article/details/79522813
https://blog.csdn.net/joychanger/article/details/51336527>>>AndroidManifest.xml
>>>activity-alias详解
https://blog.csdn.net/ahence/article/details/51648768
即activity的别名,它有一个属性叫android:targetActivity,这个属性就是用来为该标签设置目标Activity的,或者说它就是这个目标Activity的别名。
可用来设置某个Activity的快捷入口,可以放在桌面上或者通过该别名被其他组件快速调起。>>>Settings.java
//Redmine 114884 zhangdi modified for settings ui 2018 01 17 begin
public static class GestureDashboardActivity extends SettingsActivity {}
//Redmine 114884 zhangdi modified for settings ui 2018 01 17 end
//Redmine #122701 liuxiangnan added for user guide 2018.02.09,begin
public static class UserGuideActivity extends SettingsActivity { /* empty */ }
//Redmine #122701 liuxiangnan added for user guide 2018.02.09,end
>>>SettingsActivity.java
>>>onCreate()
>>>setContentView(mIsShowingDashboard ? R.layout.settings_main_dashboard : R.layout.settings_main_prefs);
//mIsShowingDashboard,当前类是否为Settings.class,即进入方式为点击launcher上的图标进入的主设置界面
>>>launchSettingFragment(initialFragmentName, isSubSettings, intent);
//加载布局
>>>launchSettingFragment()
if (!mIsShowingDashboard && initialFragmentName != null) {…}
else{
// Show search icon as up affordance if we are displaying the main Dashboard,如果我们正在显示主仪表板,请显示搜索图标
mDisplayHomeAsUpEnabled = true;
mInitialTitleResId = R.string.dashboard_title;
switchToFragment(DashboardSummary.class.getName(), null /* args */, false, false, mInitialTitleResId, mInitialTitle, false);
}
>>>switchToFragment()
>>>DashboardSummary.java
//对于它我们主要是想知道它的数据加载,它是怎么加载自己的子项的。
对子项的数据获取在updateCategoryAndSuggestion()中得到实现。>>>对于第一级菜单的加载。在AndroidManifest.xml中的配置如下列图:
例子:
<activity android:name=".Settings$NetworkDashboardActivity"
android:taskAffinity="com.android.settings"
android:label="@string/network_dashboard_title"
android:icon="@drawable/ic_settings_wireless"
android:parentActivityName="Settings">
<intent-filter android:priority="1">
<action android:name="android.settings.WIRELESS_SETTINGS" />
<action android:name="android.settings.AIRPLANE_MODE_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.VOICE_LAUNCH" />
</intent-filter>
<intent-filter android:priority="11">
<action android:name="com.android.settings.action.SETTINGS"/>
</intent-filter>
//类别,这里com.android.settings.category.ia.homepage代表一级页面
<meta-data android:name="com.android.settings.category" android:value="com.android.settings.category.ia.homepage"/>
//跳转到的fragment
<meta-data android:name="com.android.settings.FRAGMENT_CLASS" android:value="com.android.settings.network.NetworkDashboardFragment"/>
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED" android:value="true" />
</activity>
>>>第二级菜单的加载
第一级菜单是完全动态的加载,但二级菜单则是动态加载和静态xml布局文件.
例子:第一级菜单System下的二级菜单。
跳转的Fragment是 SystemDashboardFragment.java,该类继承DashboardFragment.java。
>>>父类 DashboardFragment.java
1.静态加载部分:
静态加载部分的实现方法为:
>>>displayResourceTiles()
>>>getPreferenceScreen()
/** 实现布局文件中的子项控件的业务逻辑
* DashboardFragment.java的子类SystemDashboardFragment.java实现getPreferenceControllers()方法,该方法加载继承于AbstractPreferenceController.java的实现业务逻辑类
*/
2.动态加载部分:
>>>refreshDashboardTiles()
注:
添加一级菜单:119639(UserGuider A15);112154(来电闪烁功能 A15)
添加二级菜单:129308(AppUpdate F1)
将一级菜单调整到二级菜单:129309(调整UserGuider位置)
Android8.0 Settings provider 数据库 新方法
https://blog.csdn.net/Aaron121314/article/details/78332628Settings.db在android6.0上的变化
https://blog.csdn.net/kv110/article/details/51520207
在framework中添加新类或者新api UpdateAPI
http://192.168.3.77:8989/wcp/webdoc/view/Pub402880cd5dc4c831015de48cbff601f8.html
https://www.cnblogs.com/zhengtu2015/p/5134287.html
编译android framework层的资源文件
https://blog.csdn.net/thinkinwm/article/details/17916873
Redmine127424 liujingjing add mediabutton in fm 20180423 beginif("com.android.fmradio".equals(appInfo.packageName)){
notiBuilder.setSmallIcon(com.android.internal.R.drawable.fm_title_icon);}
暗码处理的地方:
https://blog.csdn.net/u013398960/article/details/72899353
alps/vendor/mediatek/proprietary/packages/apps/Dialer/java/com/android/dialer/app/dialpad/DialpadFragment.java
Dynamic Shortcuts
长按应用弹出快捷菜单.
App Shortcuts是指在桌面长按app图标而出现的快捷方式, 可以为你的app的关键功能添加更快速的入口而不用先打开app,点击快捷方式可以访问应用功能, 并且这种快捷方式也可以被拖拽到桌面单独放置, 变成单独的桌面快捷方式.*****https://www.jianshu.com/p/8cfd506caa07 –>构建回退栈的例子(静态和动态配置都可以)
*****https://www.jianshu.com/p/fddc8d5f8d64 —>最佳实践!
https://blog.csdn.net/qibin0506/article/details/52878690
1 Static Shortcuts
//配置多个intent,点击打开最后一个intent的页面,前面的intent用来构建回退栈
runOnUiThread
https://www.aliyun.com/jiaocheng/4598.html
重新回过头来看 runOnUiThread()的源码:final Handler mHandler = new Handler();
private Thread mUiThread;
// …
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
// …
}首先在主线程里通过无参的构造方法创建一个Handler,这个Handler是指向主线程的。
当执行runOnUiThread()时,当前线程不是主线程,调用mHandler.post(action),将Runnable添加到主线程的消息队列中
这样,Runnable的语句就是在主线程执行的了。注意:
用这种方式创建ProgressDialog就比较方便,或者刷新adapter也比使用Thread+Handler方便。
如果不是在activity中创建,需要在前面加上((Activity)mContext).
https://blog.csdn.net/liuweiballack/article/details/49800829
android:configuration 处理屏幕旋转和语言切换等问题
https://blog.csdn.net/lyhhj/article/details/48789705
Android Studio导入github项目详解
问题1:
我们要改3个文件
1 根目录下的build.gradle文件中的build:gradle版本
2 gradle文件夹下的gradle-wrapper.properties文件中的distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
3 app目录下build.gradle的依赖库
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:26.+'问题2:
https://blog.csdn.net/CHENYUFENG1991/article/details/74136439?locationNum=10&fps=1
Unregistered VCS root detected. The directory…is under Git, but is not registered in the Settings
问题:
修改AS中的代码,git status后会有一些无关代码的文件发生变化.
这种情况,你是在设计gitignore 之前就没考虑好的!现在的措施是:
你要先去删除远程的 .idea 目录。rm -rf .idea (这样会删掉你本地的,不过你重新打开一次项目就有会自动给你生成了)
git add -A .
提交
git pullpull 后再看看同步后,远程的删掉没有;如果本地有,再次重复下。
干净后,这下 git rm -r –cached .idea 取消跟踪
再push 吧
camera快速编译
touch vendor/mediatek/proprietary/hardware/mtkcam/legacy/v1/common/paramsmgr/feature/custom/custom.cpp &&
./mk VP501_H5019_Rokit mm vendor/mediatek/proprietary/hardware/mtkcam/legacy/v1/common/paramsmgr/ &&
./mk VP501_H5019_Rokit mm vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6580/v1/common/paramsmgr/adb push
adb push out/target/product/k80hd_bsp_fwv_512m/vendor/lib/libcam.paramsmgr.so vendor/lib/libcam.paramsmgr.so
[FAQ17665] 快速修改调试Feature Table
[FAQ14389] Feature Table加载原理和调试方法修改camera FOV此项使用快速编译 无效!
Content provider 中getPathSegments用途
–getPathSegments得到uri的path部分,并拆分,去掉"/",取到第一个元素(从第0个开始)。
比如:content://"+FirstProvierMetaData.AUTHORIY+"/users /1"
//getPathSegments()得到的是users 和 1,get(1)会得到1qb.appendWhere(UserTableMetaData._ID+"="+uri.getPathSegments().get(1));
Demo:
Uri uri = Uri.parse("content://com.haha.mycontentproviderdemo.NoteContentProvider/notes");
Uri myUri = Uri.withAppendedPath(uri, "#/2");
List<String> list = myUri.getPathSegments();
int i = 0;
for (Iterator iterator = list.iterator(); iterator.hasNext(); i++) {
String string = (String) iterator.next();
Log.i("test", "集合里的元素为:" + string);
Log.i("test", "集合中下标为 " + i +"的String类型元素为:"+ list.get(i));
}
Log:
01-01 19:32:51.633 8516-8516/com.example.test2 I/test: 集合里的元素为:notes
01-01 19:32:51.634 8516-8516/com.example.test2 I/test: 集合中下标为 0的String类型元素为:notes
01-01 19:32:51.634 8516-8516/com.example.test2 I/test: 集合里的元素为:#
01-01 19:32:51.634 8516-8516/com.example.test2 I/test: 集合中下标为 1的String类型元素为:#
01-01 19:32:51.634 8516-8516/com.example.test2 I/test: 集合里的元素为:2
01-01 19:32:51.634 8516-8516/com.example.test2 I/test: 集合中下标为 2的String类型元素为:2
Failed to resolve: com.android.support:appcompat-v7:27.0.1问题解决
https://blog.csdn.net/waa_studio/article/details/78732460
sdk版本和build tool版本不一致
在project下的build.gradle文件下加上
allprojects {
repositories {
jcenter()
+ maven { url "https://jitpack.io" }
+ maven { url "https://maven.google.com" }
}
}android gradle plugin update recommend
To take advantage of all the latest features (such as Instant Run), improvements and security fixes, we strongly recommend that you update the Android Gradle plugin to version 2.3.3 and Gradle to version 3.3. You can learn more about this version of the plugin from the release notes.Unregistered VCS root detected
The directory /home/chenghao/APK/QianBaoDai is under Git, but is not registered in the Settings.
Sources for 'Android API 25 Platform' not found
方法:降低sdk版本的方式
Intellij IDEA 提交代码到远程GitHub仓库
https://blog.csdn.net/longge92345/article/details/51902275
解决ListViews适配器notifyDataSetChanged()无效问题
http://blog.csdn.net/csdn_lqr/article/details/50947825
声明:
1,要使mAdapter.notifyDataSetChanged()有效的前提条件是数据发生变化!!!
2,new操作在java中是创建一个新的对象,实际上跟c语言一样,会在内存中开辟一个新的空间,这里就会牵扯到数据的址传递和值传递问题。
<meta-data>标签
https://blog.csdn.net/c418098445/article/details/45248765
<meta-data>元素用name-value对的格式给其父组件提供任意可选的数据。一个组件元素能够包含任意多个<meta-data>子元素,所有这些元素中定义的值会被收集到一个Bundle对象中,并且提供给组件的PackageItemInfo.metaData属性字段<meta-data android:name="string" android:resource="resource specification" android:value="string" />
这是该元素的基本结构.可以包含在 <activity> <activity-alias> <service> <receiver>四个元素中。1.在Activity的应用。
xml代码段:
<activity>
<meta-data android:name="myMsg" android:value="hello"></meta-data>
</activity>
java代码段:
ActivityInfo info=this.getPackageManager() .getActivityInfo(getComponentName(),PackageManager.GET_META_DATA);
String msg=info.metaData.getString("myMsg");2.在application的应用。
xml代码段:
<application>
<meta-data android:value="hello" android:name="myMsg"></meta-data>
</application>
java代码段:
ApplicationInfo appInfo = this.getPackageManager().getApplicationInfo(getPackageName(),PackageManager.GET_META_DATA);
String msg=appInfo.metaData.getString("myMsg");3.在service的应用。
xml代码段:
<service android:name="MetaDataService">
<meta-data android:value="hello" android:name="myMsg"></meta-data>
</service>
java代码段:
ComponentName cn=new ComponentName(this, MetaDataService.class);
ServiceInfo info=this.getPackageManager().getServiceInfo(cn, PackageManager.GET_META_DATA);
String msg=info.metaData.getString("myMsg");4.在receiver的应用。
xml代码段:
<receiver android:name="MetaDataReceiver">
<meta-data android:value="hello" android:name="myMsg"></meta-data>
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"></action>
</intent-filter>
</receiver>
java代码段:
ComponentName cn=new ComponentName(context, MetaDataReceiver.class);
ActivityInfo info=context.getPackageManager().getReceiverInfo(cn, PackageManager.GET_META_DATA);
String msg=info.metaData.getString("myMsg");
Modem编译
先拉modem代码编译之前首先查找准确的mak文件:
1.首先在projectConfig.mk文件中查找
CUSTOM_MODEM=编译生成 modem 文件夹名称
在对应项目的sagereal/custom/modem/路径下找到相对应的modem文件夹名称
备注:
80m和80n平台对应路径在vendor/mediatek/proprietary/modem/目录下
进入对应的modem文件夹找到DbgInfo形式开头的文件,例如:DbgInfo_WR8.W1449.MD.WG.MP_XXXXXXX_MOLY_WR8_W1449_MD_WG_MP_V91_5_P3_2017_02_16_14_20_1_wg_n
此文件中MP_和_MOLY之间名称为此项目对应的正确的modem文件名称。把整个modem源码以modem命名放在alps相同目录下
在script文件夹中的project.mk中把要编的modem添加上去
eg: modem1=VP25D_H508_BAND1_HSPA
在modem目录下,执行 ./mk,会生成modemtmp和output两个文件夹,output为输出的所需的文件夹把output目录copy到vendor/mediatek/proprietary/custom/common/modem/
或者sagereal/custom/modem/对应的modem然后重命名即可。替换之后验证:./mk {project} clone
./mk {project} update-modem : 之后刷机验
编译完成之后,对比新生成的.mak文件和上述modem文件夹中旧的.mak文件,进一步确认mak文件是否选择正确,然后再执行其他操作。
Notification
在创建Notification实例的过程中调用setlargeicon(),传入的参数是Bitmap。
但是只有res/drawable下的ic_launcher.png。
就需要用到下面:
Android中Bitmap, Drawable, Byte,ID之间的转化 – – ITeye博客Android之利用RemoteViews自定义Notification
https://blog.csdn.net/loveyaozu/article/details/51178707通知栏通知和小部件的开发过程中经常会用到RemoteViews。它们在更新UI的时候无法像Activity和Fragment那样直接更新,前面讲过,因为它是跨进程的view,更确切一点来说的话,它是运行在SystemServer进程中。为了能够跨进程更新界面,RemoteViews提供了一些列可以跨进程更新UI的方法,内部有一些列的set方法,这些方法都是View的子集。
通话过程中收到短信或蓝牙,无声音提醒
https://blog.csdn.net/self_study/article/details/51055769
alps/frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java wuxiaoming
116115
vendor/mediatek/proprietary/packages/apps/Mms/src/com/android/mms/transaction/MessagingNotification.java
SystemProperties
参看http://blog.csdn.net/yin1031468524/article/details/67640786
Android系统源码中,存在大量的SystemProperties.get或SystemProperties.set,通过这两个接口可以对系统的属性进行读取/设置,看着挺简单的就是调用get或set就能获取或设置系统属性,其实并不然。曾经也遇到过有关的坑,所以就总结了下,这样以后自己就不会在再次入坑了,接下来了正题吧
1、SystemProperties的使用
SystemProperties的使用很简单,在SystemProperties.java中所以方法都是static,直接通过SystemProperties.get(String key)或SystemProperties.set(String key, String val)就可以了,系统属性都是以键值对的形式存在即name和value需要注意的是对name和value的length是有限制的,name的最大长度是31,value最大长度是91
webview加载网页出现("找不到网页net:err_unknown_url_scheme")
解决方法:以"http","https"开头的url在本页用webview进行加载,其他链接进行跳转
private class MyWebViewClient extends WebViewClient{
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(url.startsWith("http:") || url.startsWith("https:") ) {
view.loadUrl(url);
return false;
}else{
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
}
}
长按1拨打信箱电话接通时弹出拨号盘:
CallButtonPresenter.java
–>getActivity().showDialpadFragment(true /* show */, true /* animate */);
–>public void onStateChange(InCallState oldState, InCallState newState, CallList callList) {}
–>public void onInCallButtonUiReady(InCallButtonUi ui){}InCallFragment.java
–>onButtonGridCreated()
InCallButtonGridFragment.java
–>public interface OnButtonGridCreatedListener {
void onButtonGridCreated(InCallButtonGridFragment inCallButtonGridFragment);
void onButtonGridDestroyed();ButtonController getButtonController(@InCallButtonIds int id);
}
InCallButtonGridFragment.java
–>
@Override
public void onViewCreated(View view, @Nullable Bundle bundle) {
super.onViewCreated(view, bundle);
buttonGridListener.onButtonGridCreated(this);
}
2个分析方法如下:
一:
在拨通界面也可以通过点击keypad键弹出拨号盘,分析如下:
通过id incall_second_button
找到incall_button-gird.xml和InCallButtonGirdFragment.java
–InCallButtonGirdFragment.java
里面有接口:
/** Interface to let the listener know the status of the button grid. */
public interface OnButtonGridCreatedListener {
void onButtonGridCreated(InCallButtonGridFragment inCallButtonGridFragment);
void onButtonGridDestroyed();
ButtonController getButtonController(@InCallButtonIds int id);
}
里面的生命周期方法:
public void onViewCreated(View view, @Nullable Bundle bundle) {
super.onViewCreated(view, bundle);
android.util.Log.d("chenghao222","inCallbuttonGirdFragment.java–>onViewCreated()");
buttonGridListener.onButtonGridCreated(this);
}
调用了buttonGridListener.onButtonGridCreated(this);
接下来看哪一个类实现了该接口 OnButtonGridCreatedListener,并重写了 onButtonGridCreated()方法。
grep 发现InCallFragment.java实现了该接口,并重写了 onButtonGridCreated()方法
在重写的方法里有:
inCallButtonUiDelegate.onInCallButtonUiReady(this);//inCallButtonUiDelegate是接口。
再看谁实现了他:CallButtonPresenter.java实现的,并重写了onInCallButtonUiReady()方法,里面调用了onStateChange()方法。
onStateChange()方法中调用了getActivity().showDialpadFragment(true /* show */, true /* animate */);//弹出拨号盘,bull's eye!
和updateButtonStates();
二:
由于通过点击keypad键弹出拨号盘,可以分析按键的点击事件:
在InCallButtonGirdFragment.java中的onCreateView()中有
buttons[1] = ((CheckableLabeledButton) view.findViewById(R.id.incall_second_button));
CheckableLabeledButton.java中有:接口
/** Callback interface to notify when the button's checked state has changed */
public interface OnCheckedChangeListener {
void onCheckedChanged(CheckableLabeledButton checkableLabeledButton, boolean isChecked);
}
ButtonController.java中的内部类、抽象类 CheckableButtonController 实现了这个接口,并重写了onCheckedChanged()方法,并在其中调用doCheckedChanged(isChecked)抽象方法。
abstract class SimpleCheckableButtonController extends CheckableButtonController ;
class DialpadButtonController extends SimpleCheckableButtonController {};终于实现了doCheckedChanged(isChecked)方法!在方法内调用了
delegate.showDialpadClicked(isChecked);
CallButtonPresenter.java实现了inCallButtonUiDelegate接口,重写了showDialpadClicked()方法。
showDialpadClicked()方法中调用 getActivity().showDialpadFragment(checked /* show */, true /* animate */); 实现点击keypad键弹出拨号盘!
多次解绑服务(unBindService)抛出异常原因解析
http://blog.sina.com.cn/s/blog_675b4b8d0102vwc0.html查看源码
总结一下:
1. 绑定服务,首先要做的事情就是先用Map记录当前绑定服务所需的一些信息。 然后启动服务。
2. 解绑服务,先从早前的Map集合中移除记录,然后停止服务。
3. 如果再次解绑,无非就是再到这个map集合中找找有没有这条记录,没有就抛出服务没有注册的异常,也就是早前根本没有注册过任何服务。
怎么合patch:
1.申请patch,下载patch。
2.select left folder For compare,compare to “文件名”。
3.进入Bcomparer,合入保存再编译刷机验证。
注:(先切换到master分支下)
删除某个文件 rm kernel-3.18/tools/dct/old_dct/MT8590.fig
删除某个文件夹 rm -r vendor/mediatek/proprietary/external/libhotknot_device/src/mt6737/
再一一删除各个文件或文件夹 git rm kernel-3.18/tools/dct/old_dct/MT8590.fig…
git add ./ 或者git add . 添加所有改动的文件,exe文件会被添加;
git add alps/vendor/google/ //该路径下的改动的文件会被添加
git add sagereal/product/ //该路径下的改动的文件会被添加
提交 git commit -m "ALPS03422589(For_sr6737t_65_n_alps-mp-n0.mp1-V1.0.2_P109)" //至此已完成主分支的合patch操作
接下来合到各个分支:
再切换到各个分支,用git cherry-pick fd1b0a0587ba1d36bac6f0a998840c5f2f4ced9a(修改好的分支的某次commit ID)
(也可以用merge方法,但我不知道!)
执行git cherry-pick fd1b0a0587ba1d36bac6f0a998840c5f2f4ced9a后,不用commit,可以使用git log 查看提交,接着push就可以了。
patch释放后,要拉代码,然后将patch上传patch服务器下。然后有专门的人负责合patch到master以及各个分支。
注:git cherry-pick冲突后,解决冲突后,再add,commit,push
——————————————————————————————————————————————–
https://blog.csdn.net/liuhaomatou/article/details/54410361
怎么把自己的本地修改做成patch :
先修改代码,再add,再 git commit -m "modify for cts error; checker:rongweidi",再git log 查看最后一次commit id,
再git format-patch -1 fb883372cb2b808de092dc744351d803db99c06b,这样在工程下就生成了一个patch怎么合本地生成的patch:
把具体patch放到工程目录下,git am –signoff 0001-cts-theme-error-checker-zhangqi.patch打patch
git apply –stat 0001-cts-theme-error-checker-zhangqi.patch
git apply –check 0001-cts-theme-error-checker-zhangqi.patch
git am –signoff 0001-cts-theme-error-checker-zhangqi.patchgit format-patche commit-id //会生成该条commit-id之后的每次提及对应的patch
AOSP宏控
1.Config.xml宏控
1>在symbols.xml 声明宏控的类型 (alps/vendor/mediatek/proprietary/frameworks/base/res/res/values/symbols.xml)
eg:
<!–Redmine102280 chencong modify for camera flash when battery level is under 15% 2017.08.11 begin–>
<java-symbol type="bool" name="sagereal_low_battery_level_warning" />
<!–Redmine102280 chencong modify for camera flash when battery level is under 15% 2017.08.11 end–>2>在config.xml 给宏控赋值 (alps/vendor/mediatek/proprietary/frameworks/base/res/res/values/config.xml)
eg:
<!–Redmine102280 chencong modify for camera flash when battery level is under 15% 2017.08.11 begin–>
<bool name="sagereal_low_battery_level_warning">false</bool>
<!–Redmine102280 chencong modify for camera flash when battery level is under 15% 2017.08.11 end–>3>在源码文件中调用该宏控
注:bool型的值被写入JavaOption.java文件
i. alps/vendor/mediatek/proprietary/frameworks/base/res/res/values/config.xml中定义宏控,格式:sagereal_xxx_xxx, xxx用于描述添加宏控的作用
eg:<bool name="sagereal_show_record_menu">true</bool>ii. alps/vendor/mediatek/proprietary/frameworks/base/res/res/values/symbols.xml中定义宏控的类型: <java-symbol type="bool" name="sagereal_show_record_menu" />
iii.在需要调用宏控的地方调用该宏控getContext().getResources().getBoolean(com.mediatek.internal.R.bool.sagereal_show_record_menu)
因为所加的内容被编译在com.mediatek.internal包,所以此处调用com.mediatek.internal.R注:*****在对应项目的projectconfig.mk文件下可以对宏重新赋值。
clone_mmi.sh脚本文件作用:
将sagereal下对应项目的宏控的值写到alps/vendor/mediatek/proprietary/frameworks/base/res/res/values/config.xml中2.ro值宏控
适用于获取不到context的地方调用
i.在sagereal/mk/{project}/ProjectConfig.mk中添加宏控:SAGEREAL_FACTORYTEST_LED = yes
宏控格式:SAGEREAL_XXX_XXX, XXX问题修改的描述
ii.在alps/device/mediatek/common/device.mk中添加ro值的控制
ifeq ($(strip $(SAGEREAL_FACTORYTEST_LED)),yes)
PRODUCT_PROPERTY_OVERRIDES += ro.sr_ftest_led=1
endif
iii.在源码文件中调用宏控,使用SystemProperties.get(“ro.sr_ftest_led”, 0).equals(“1”)来判断,注意导包,此处无需获取context, ro.sr_ftest_led一旦没设置,此处获取出来为空, 可使用: adb shell getprop ro.sr_ftest_led 获取或检查是否设置加宏具体要怎么操作呢?
1.alps/vendor/mediatek/proprietary/frameworks/base/res/res/values/config.xml中定义宏控名称及默认值(一版默认原生的流程false)
2.alps/vendor/mediatek/proprietary/frameworks/base/res/res/values/symbols.xml中定义类型
3.Java文件中调用宏控来控制代码流程
4.ProjectConfig.mk中指定需要修改的宏控名称及修改的值
5.clone_mmi.sh中指定path及writexml的宏控名称
将数据库文件pull出来:
adb pull /data/data/com.example.databasetest/databases/BookStore.db将数据库文件push到手机:
adb push BookStore.db /data/data/com.example.databasetest/databases/打开终端
sqlitebrowser//打开可视化Sqlite例子:
chenghao@chenghao-ThinkStation-P300:~$ adb root
adbd is already running as root
chenghao@chenghao-ThinkStation-P300:~$ adb remount
remount succeeded
chenghao@chenghao-ThinkStation-P300:~$ adb shell
Chinchilla:/ # cd data/data/com.google.android.gsf/databases/
Chinchilla:/data/data/com.google.android.gsf/databases # ls
googlesettings.db gservices.db subscribedfeeds.db
Chinchilla:/data/data/com.google.android.gsf/databases # sqlite3 gservices.db
SQLite version 3.19.4 2017-08-18 19:28:12
sqlite> select * from main where name = "android_id"
…> ;
sqlite> .headers on
sqlite> select * from main;
name|value
digest|1-da39a3ee5e6b4b0d3255bfef95601890afd80709
https://onlinesso.mediatek.com/FAQ#/SW/FAQ12393
Software #117876
[传音需求—–图库] 图库放大比例,双击放大2倍,双指缩放最大到3.5倍
修改sim卡默认铃声:
project.config
clone_integration.sh
alps/build/target/product/full_base.mk
alps/frameworks/base/data/sounds/AllAudio.mk
注意full_base.mk文件中修改的内容每行末尾都要加 \
不然会clone失败
怎样修该代码:
如果在sageral拷贝下的改动完成之后,
使用:
./mk UP19_H353_ODO_new clone
将sageral下的所有改动 克隆 到alps下面。然后模块编译:
./mk UP19_H353_ODO_new mm packages/apps/SagerealApp/ChromeCustomizations/adb remount
push apk到手机:
adb push out/target/product/sr6572_wet_l/system/vendor/app/ChromeCustomizations/ChromeCustomizations.apk system/vendor/app/ChromeCustomizations/ChromeCustomizations.apk提交代码:
a. git pull // 更新到最新代码
b. 修改代码
c. git status // 当前状态,可以查看修改了哪些代码,
d. git add +文件路径 //最好新拉工程,将需要提交的移到新拉的工程上再操作 如果确认所有的修改都是需要上传到服务器上的可以使用:git add . // 将所有变动都上传
e. git commit –m, 在出现的界面数据上传log信息,格式同svn:
Redmine书写格式:
Submitter:
checker:
Tester:
Bug:
Files:
M alps/vendor/mediatek/proprietary/packages/apps/Dialer/java/com/android/incallui/CallButtonPresenter.java
Comment:
Date: 2018-06-21android.util.Log.d("chenghao","");
f. git push origin XXX // XXX表示当前分支 比如 master xxxbranch
git status
git add sagereal/pcb/WE552_H5018_commom/alps/vendor/mediatek/proprietary/custom/mt6755/hal/imgsensor_src/cfg_setting_imgsensor.cpp 修改多处则:add .
git status
git diff
git commit -m "modify for submit: check: date: "
git push origin dev_fr //如果push不上去,说明这期间有人更新了代码,所以要git pull再git push origin dev_fr。