./mediatek/config/common/ProjectConfig.mk中找到 PRODUCT_LOCALES= 对该行进行修改
修改默认时区
修改frameworks/base/core/java/com/android/internal/os/RunTimeInit.java文件
commonInit方法
TimezoneGetter.setInstance(new TimezoneGetter() {
@Override
public String getId() {
Stringzoneinfo = SystemProperties.get("persist.sys.timezone");
if(zoneinfo==null||zoneinfo.length()==0)
{
SystemProperties.set("persist.sys.timezone","America/Santiago");//设置时区 America/Santiago字符串可以在Time_zones_by_country.xml(frameworks\base\core\res\res\xml)文件中查找
}
return SystemProperties.get("persist.sys.timezone");
}
});
获得手机屏幕的宽度和高度:
public static int getScreenWidth(Context context)
{
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.widthPixels;
}
/**
* dp转px
*
* @param context
* @param val
* @return
*/
public static int dp2px(Context context, float dpVal)
{
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpVal, context.getResources().getDisplayMetrics());
}
/**
* sp转px
*
* @param context
* @param val
* @return
*/
public static int sp2px(Context context, float spVal)
{
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
spVal, context.getResources().getDisplayMetrics());
}
/**
* px转dp
*
* @param context
* @param pxVal
* @return
*/
public static float px2dp(Context context, float pxVal)
{
final float scale = context.getResources().getDisplayMetrics().density;
return (pxVal / scale);
}
/**
* px转sp
*
* @param fontScale
* @param pxVal
* @return
*/
public static float px2sp(Context context, float pxVal)
{
return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
}
如果需要apkA和apkB共享一个数据库的话,则需要将其android:sharedUserId设为相同就可以了,例如apkA中的manifest.xml文件如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.demo.a1"
android:sharedUserId="com.c">
注意,这是apkB也需要将android:sharedUserId的值设置为:"com.c",此时才可以访问apkA中的数据库:
此时可以通过如下方式得到一个context,通过该context我们就可以访问apkA中的数据了:
Context friendContext = this.createPackageContext(
"com.android.demo.a1",
Context.CONTEXT_IGNORE_SECURITY);
1.Display display = getWindowManager().getDefaultDisplay();
boolean isPortrait = display.getWidth() < display.getHeight();
2.DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics();
Boolean isPortrait = dm.widthPixels < dm.heightPixels;
3.boolean isPortrait = false ;
if(android.content.res.Configuration.orientation == android.content.res.Configuration.ORIENTATION_PORTRAIT)
{
isPortrait = true ;
}
else if(android.content.res.Configuration.orientation == android.content.res.Configuration.ORIENTATION_LANDSCAPE)
{
isPortrait = false ;
}
注意第三种方式,需要在manifest.xml中的application标签中添加如下配置:
//在Application标签中加入
android:configChanges="orientation"
利用android自带的zipalign来优化我们的程序:
zipalign -v 4 source.apk destination.apk
简单利用monkey来测试程序性能:monkey -p com.android.camera -v 500 顾名思义com.android.camera 是我们需要测试的应用程序的包名
android实现简单的倒计时效果:
在android中为我们提供了这样的一个类CountDownTimer,可以来实现简单的倒计时效果:
class MyCount extends CountDownTimer {
public MyCount(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
@Override
public void onFinish() {
tv.setText("finish");
}
@Override
public void onTick(long millisUntilFinished) {
tv.setText("请等待30秒(" + millisUntilFinished / 1000 + ")...");
}
}
然后,在oncreate方法中:
tv = (TextView) findViewById(R.id.id_text);
final MyCount mc = new MyCount(30000,1000);
mc.start();
android实现抖动效果:
第一步:准备两个动画效果的XML文件,加入到 res/anim/目录下:
Shake.xml文件:
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:toXDelta="10"
android:duration="1000"
android:interpolator="@anim/cycle_7" />
cycle_7.xml文件:
<cycleInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:cycles="7" />
第二步: //代码使用动画效果:
Animation shake = AnimationUtils.loadAnimation(this, R.anim.shake);//加载动画资源文件
findViewById(R.id.xxxx).startAnimation(shake); //给组件播放动画效果
下面我们看一下这个函数:
scrollView.fullScroll(ScrollView.FOCUS_DOWN);滚动到底部
scrollView.fullScroll(ScrollView.FOCUS_UP);滚动到顶部
需要注意的是,该方法不能直接被调用
因为Android很多函数都是基于消息队列来同步,所以需要一部操作,
addView完之后,不等于马上就会显示,而是在队列中等待处理,虽然很快,但是如果立即调用fullScroll, view可能还没有显示出来,所以会失败
应该通过handler在新线程中更新
handler.post(new Runnable() {
@Override
public void run() {
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
});
android流量监控:
public void getAppTrafficList(){
//获取所有的安装在手机上的应用软件的信息,并且获取这些软件里面的权限信息
PackageManager pm=getPackageManager();//获取系统应用包管理
//获取每个包内的androidmanifest.xml信息,它的权限等等
List<PackageInfo> pinfos=pm.getInstalledPackages
(PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_PERMISSIONS);
//遍历每个应用包信息
for(PackageInfo info:pinfos){
//请求每个程序包对应的androidManifest.xml里面的权限
String[] premissions=info.requestedPermissions;
if(premissions!=null && premissions.length>0){
//找出需要网络服务的应用程序
for(String premission : premissions){
if("android.permission.INTERNET".equals(premission)){
//获取每个应用程序在操作系统内的进程id
int uId=info.applicationInfo.uid;
//如果返回-1,代表不支持使用该方法,注意必须是2.2以上的
long rx=TrafficStats.getUidRxBytes(uId);
//如果返回-1,代表不支持使用该方法,注意必须是2.2以上的
long tx=TrafficStats.getUidTxBytes(uId);
if(rx<0 || tx<0){
continue;
}else{
Toast.makeText(this, info.applicationInfo.loadLabel(pm)+"消耗的流量--"+
Formatter.formatFileSize(this, rx+tx), Toast.LENGTH_SHORT);
}
}
}
}
}
}
另外还有其他的一些方法:
static long getMobileRxBytes()//获取通过Mobile连接收到的字节总数,但不包含WiFi
static long getMobileRxPackets()//获取Mobile连接收到的数据包总数
static long getMobileTxBytes()//Mobile发送的总字节数
static long getMobileTxPackets()//Mobile发送的总数据包数
static long getTotalRxBytes()//获取总的接受字节数,包含Mobile和WiFi等
static long getTotalRxPackets()//总的接受数据包数,包含Mobile和WiFi等
static long getTotalTxBytes()//总的发送字节数,包含Mobile和WiFi等
static long getTotalTxPackets()//发送的总数据包数,包含Mobile和WiFi等
static long getUidRxBytes(int uid)//获取某个网络UID的接受字节数
static long getUidTxBytes(int uid) //获取某个网络UID的发送字节数
设置软件盘自动弹出:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
android格式化字符串:
比如,我在string.xml中定义了这样一条字符串:
<string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string>
代码中需要这样写:
String tempText = getResources().getString(R.string.welcome_messages);
TextView text = (TextView) findViewById(R.id.id_text);
text.setText(tempText.format(tempText,"haha",2));
关于audioManager中的几种获取焦点的不同:
1.AUDIOFOCUS_GAIN 这种方式会获得焦点,可是在我们放弃焦点的时候,之前的那个音频不能自动播放
2. AudioManager.AUDIOFOCUS_GAIN_TRANSIENT 这种方式会获得焦点,当放弃焦点的时候,之前的音频同样会继续播放,可是如果会暂时取消之前音频的notification
3.AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE ,AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
这两种方式不会取消notification,可是对于FM是不起作用的。
关于adb logcat的常见用法:
adb logcat | grep MyApp
adb logcat | grep -i myapp #忽略大小写。
要过滤 tag 为 MyApp 和 MyActivity 的输出:
adb logcat | grep -v "^..MyApp\|^..MyActivity"
有时需要分析 log 文件,过滤 log 文件还是使用 grep。例如 log 文件为 myapp.log,要匹配 tag 为 MyApp 和 MyActivity 的输出,然后输出到 newmyapp.log:
cat myapp.log | grep "^..MyApp\|^..MyActivity" > newmyapp.log
使用android:background="@drawable/bg"属性设置背景,android:cacheColorHint="@android:color/transparent"设置item背景为透明,解决在滑动item出现黑色背景的问题
使用Martix(android.graphics.Matrix)类中的postScale()方法结合Bitmap来实现缩放图片的功能
Bitmap bmp = BitmapFactory.decodeResource(getResource(),R.drawalbe.icon1)
int bmpwidth = bmp.getWidth();
int bmpheight = bmp.getHeight();
Matrix matrix = new Matrix();
matrix.postScale(width,height);
Bitmap bm = Bitmap.createBitmap(bmp,0,0,bmpwidth,bmpheight ,matrix,true);
imageView.setImageBitmap(bm);
requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉标题栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);// 设置全屏
// 设置横屏显示
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
// 选择支持半透明模式,在有surfaceview的activity中使用。
getWindow().setFormat(PixelFormat.TRANSLUCENT);
从Android 2.2开始系统新增了一个缩略图ThumbnailUtils类,位于framework的android.media.ThumbnailUtils位置,可以帮助我们从mediaprovider中获取系统中的视频或图片文件的缩略图,该类提供了三种静态方法可以直接调用获取。
1.
static Bitmap createVideoThumbnail(String filePath, int kind) //获取视频文件的缩略图,第一个参数为视频文件的位置,比如/sdcard/android123.3gp,而第二个参数可以为MINI_KIND或 MICRO_KIND最终和分辨率有关
2.
static Bitmap extractThumbnail(Bitmap source, int width, int height, int options) //直接对Bitmap进行缩略操作,最后一个参数定义为OPTIONS_RECYCLE_INPUT ,来回收资源
3.
static Bitmap extractThumbnail(Bitmap source, int width, int height) // 这个和上面的方法一样,无options选项
activity切换动画
public void onClick(View v) {
Intent intent = new Intent(ActivityAnim.this,ActivityTwo.class);
startActivity(intent);
overridePendingTransition(R.anim.act_enter,R.anim.act_exit);
}
overridePendingTransition(int ,int)函数,第一个参数为activity显示动画,第二个参数为退出动画,两个动画的xml文件存放在anim文件夹下
popwindow通过setAnimationStyle(int animationStyle)函数来设置动画效果
android:windowEnterAnimation表示进入窗口动画
android:windowExitAnimation表示窗口退出动画
在res/values/style.xml代码:
<style name="PopupAnimation" parent="android:Animation" mce_bogus="1">
<item name="android:windowEnterAnimation">@anim/popup_enter</item>
<item name="android:windowExitAnimation">@anim/popup_exit</item>
</style>
/***//**
* 图片去色,返回灰度图片
* @param bmpOriginal 传入的图片
* @return 去色后的图片
*/
public static Bitmap toGrayscale(Bitmap bmpOriginal) {
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpOriginal, 0, 0, paint);
return bmpGrayscale;
}
/***//**
* 把图片变成圆角
* @param bitmap 需要修改的图片
* @param pixels 圆角的弧度
* @return 圆角图片
*/
public static Bitmap toRoundCorner(Bitmap bitmap, int pixels) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap
.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = pixels;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
设置背景样式:
<style name="TransparentStyleBottom">
<item name="android:windowIsTranslucent">true</item><!--半透明 -->
<item name="android:windowNoTitle">true</item><!--无标题-->
<item name="android:windowBackground">@android :color/transparent</item><!--背景透明 -->
<item name="android:backgroundDimEnabled">true</item><!--模糊-->
</style>
android TextView图文混写 嵌入表情
private void setImageText()
{
//根据ID获取图像的Bitmap对象
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
//创建imageSpan对象
ImageSpan imageSpan = new ImageSpan(this, bitmap);
//创建一个SpannableString对imageSpan进行封装
SpannableString spannableString = new SpannableString("icon哇咔咔");
//用ImageSpan对象替换icon
spannableString.setSpan(imageSpan, 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv_hello.setText(spannableString);
}
在Android加载到内存的Bitmap是不允许修改的,只能够在其副本上修改和作画。那么如何创建一个原图的副本呢?
需要以下这些步骤:
①准备一个和原图宽高及配置完全一样的白纸
②白纸放在画布上
③准备一支笔
④准备一个矩阵
ImageView srcImageView = (ImageView) findViewById(R.id.iv_src);
ImageView copyImageView = (ImageView) findViewById(R.id.iv_copy);
// 原图
Bitmap srcBitmap = BitmapFactory.decodeFile("/mnt/sdcard/meinv.jpg");
srcImageView.setImageBitmap(srcBitmap);
// 拷贝
// 1. 准备一个和原图宽高完全一样的白纸
Bitmap copyBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
// 2. 把白纸放在画布上
Canvas canvas = new Canvas(copyBitmap);
// 3. 准备一支笔
Paint paint = new Paint();
// 4. 准备一个矩阵
Matrix matrix = new Matrix();
// 使用指定的矩阵绘图
canvas.drawBitmap(srcBitmap, matrix, paint);
copyImageView.setImageBitmap(copyBitmap);
pm命令的学习:
首先进入adb shell
pm list package 查看所有已经安装的程序的包名
pm list package -f 查看已经安装的程序,的apk所在的路径
pm list permissions 查看已知的所有权限
pm list permission-group 查看已知的所有的权限组
pm path com.TDiJoy.fane 列出指定包名的apk存档文件
pm install /data/3dijoy_fane.apk 安装apk
pm uninstall 包名 卸载apk
android使用自定义的第三方字体库:
// 将字体文件保存在assets/fonts/目录下,www.linuxidc.com创建Typeface对象
Typeface typeFace = Typeface.createFromAsset(getAssets(),"fonts/DroidSansThai.ttf");
// 应用字体
textView.setTypeface(typeFace);
设置popupwindow的底部弹出:
PopupWindow window = new PopupWindow(MainActivity.this);
window.setContentView(view);
window.setTouchable(true);
window.setOutsideTouchable(true);
window.setWidth(LayoutParams.MATCH_PARENT);
window.setHeight(180);
window.setAnimationStyle(R.style.popwindow);
window.showAtLocation(button, Gravity.BOTTOM,0,0);
mPopupWindow.update(); //注意在动画结束的时候需要调用update()方法,更新
// 获取在当前窗口内的绝对坐标
View.getLocationInWindow()
// 获取在整个屏幕内的绝对坐标,注意这个值是要从屏幕顶端算起,也就是包括了通知栏的高度。
View.getLocationOnScreen()
android获取id的另一种方式:
Resources resource = this.getResources();
String pkgName = this.getPackageName();
setContentView(resource.getIdentifier("main", "layout", pkgName));
akBtnId = resource.getIdentifier("btn_initAK", "id", pkgName);
Button initWithApiKey = (Button) findViewById(akBtnId);
android属性动画简单总结:
ObjectAnimator:
根据属性值设置不同的属性动画
ObjectAnimator.ofFloat(view, property, from , to)
.setDuration(500)
.start();
通过ObjectAnimator实现多动画同时操作
//这里将属性设为ocean是以为Android不认识这个属性,所以不会做任何改变,而我们要用from和to,所以就这样设定。
ObjectAnimator anim = ObjectAnimator.ofFloat(view, "ocean", from , to);//这里的参数可以设置三个,就是先小后大了。
anim.setDuration(2000);
anim.start();
anim.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float x = (Float) animation.getAnimatedValue();
view.setAlpha(x);
view.setScaleX(x);
view.setScaleY(x);
}
});
使用PropertyValuesHolder来实现ObjectAnimator的多属性动画
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(view,
PropertyValuesHolder.ofFloat("scaleX",1.0f, 0.0f,1.0f),//这里的参数设置三个,先小后大。
PropertyValuesHolder.ofFloat("scaleY", 1.0f,0.0f,1.0f),
PropertyValuesHolder.ofFloat("alpha", 1.0f,0.0f,1.0f)
).setDuration(2000);
animator.setInterpolator(new LinearInterpolator());
animator.start();
ValueAnimator的使用
ValueAnimator anim = ValueAnimator.ofFloat(from,to);
anim.setTarget(view);
anim.setDuration(2000);
anim.setInterpolator(new AccelerateInterpolator());
anim.start();
anim.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
if (orientation.equals("y")) {
view.setTranslationY((Float)animation.getAnimatedValue());
}else{
view.setTranslationX((Float)animation.getAnimatedValue());
}
}
});
AnimatorSet的使用
同时执行
ObjectAnimator obj1 = ObjectAnimator.ofFloat(view, "scaleX", 1.0f,0.5f,1.0f);
ObjectAnimator obj2 = ObjectAnimator.ofFloat(view, "scaleY", 1.0f,0.5f,1.0f);
ObjectAnimator obj3 = ObjectAnimator.ofFloat(view, "rotationX", 0.0f,180.0f,0.0f);
AnimatorSet set = new AnimatorSet();
set.setDuration(2000);
set.setInterpolator(new LinearInterpolator());
set.playTogether(obj1,obj2,obj3);
set.start();
分步执行:
ObjectAnimator obj1 = ObjectAnimator.ofFloat(view, "scaleX", 1.0f,0.5f,1.0f);
ObjectAnimator obj2 = ObjectAnimator.ofFloat(view, "scaleY", 1.0f,0.5f,1.0f);
ObjectAnimator obj3 = ObjectAnimator.ofFloat(view, "rotationX", 0.0f,180.0f,0.0f);
AnimatorSet set = new AnimatorSet();
set.setDuration(2000);
set.setInterpolator(new LinearInterpolator());
set.play(obj1).after(obj2);
set.play(obj2).after(obj3);
set.start();
AnimatorInflater是属性动画的另一种加载方式
Animator animator = AnimatorInflater.loadAnimator(context, id);
animator.setTarget(view);
animator.setDuration(2000);
animator.setInterpolator(new LinearInterpolator());
animator.start();
android图片处理:
Bitmap bitmap = null;
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.testback);
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Bitmap tempBit = Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);
int pixColor = 0;
int pixR = 0;
int pixG = 0;
int pixB = 0;
int newR = 0;
int newG = 0;
int newB = 0;
int[] pixels = new int[width * height];
bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
pixColor = pixels[width * i + j];
pixR = Color.red(pixColor);
pixG = Color.green(pixColor);
pixB = Color.blue(pixColor);
newR = (int) (0.393 * pixR + 0.769 * pixG + 0.189 * pixB);
newG = (int) (0.349 * pixR + 0.686 * pixG + 0.168 * pixB);
newB = (int) (0.272 * pixR + 0.534 * pixG + 0.131 * pixB);
int newColor = Color.argb(255, newR > 255 ? 255 : newR, newG > 255 ? 255 : newG, newB > 255 ? 255 : newB);
pixels[width * i + j] = newColor;
}
}
tempBit.setPixels(pixels, 0, width, 0, 0, width, height);
ImageView imageView = (ImageView) findViewById(R.id.imageView1);
imageView.setImageBitmap(tempBit);
git学习:
git config --global user.name "yourname"
git config --global user.email "email@example.com"
git log --pretty=oneline
将当前的版本回退到上一个版本:
git reset --hard HEAD^
回到某一个版本:
git reset --hard 需要回退的版本的序列号
通过命令:git reflog可以查看提交记录的commit id
查看分支:git branch
创建分支:git branch 分支名称
切换分支: git checkout 分支名称
创建+切换分支: git checkout -b 分支名称
合并某个分支到当前分支: git merge 分支名称
删除分支: git branch -d 分支名称
让git显示颜色,会让命令输入起来更加的醒目:
git config --global color.ui true