./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); }
<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 + ")..."); } }
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" />
<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文件夹下
<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); }
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 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 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()); } } });
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();
Animator animator = AnimatorInflater.loadAnimator(context, id); animator.setTarget(view); animator.setDuration(2000); animator.setInterpolator(new LinearInterpolator()); animator.start();
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 protected]"
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