天天看點

Android群英傳筆記

Chapter1 Android體系與系統架構

Android 高富帥 Google Linux Open Source

四層:Applications/Application Framework/Libraries+Android Runtime/Linux Kernel

Android 5.X起ART取代Dalvik Dalvik運作時編譯 ART安裝時編譯

PackageManager/ResourceManager/ActivityManager/WindowManager/ViewSystem/NotificationManager/LocationManager/TelphonyManager/Content Provider/XMPP Service

Android NDK APP AndroidManifest/Dalvik Classes/Resource Bundle/Libraries & JNI

Android SDK APP AndroidManifest/Dalvik Classes/Resource Bundle

四大元件:Activity/BroadcastReceiver/ContentProvider/Service

Intent信使

上下文Context:Application/Activity/Service都繼承自Context ApplicationContext是全局的上下文 getApplicationContext()

Android系統源碼:http://androidxref.com/    Makefile機制

/system /data目錄

/system/app/ 系統APP /system/bin/ Linux自帶元件 /system/build.prop 系統屬性檔案 /system/fonts/ 字型庫 /system/framework/ 核心檔案架構層 /system/lib/ 節享庫.so /system/media/ 提示音系統鈴聲 /system/usr 使用者配置

/data/app/ 使用者安裝的app /data/data/ App的資料資訊 /data/system/ 手機的各項系統資訊 /data/misc Wi-Fi/VPN資訊

Project/Module

app

--manifests

----AndroidManifest.xml

--java

----com.test.HelloWorld

----com.test.HelloWorld(test)

----com.test.HelloWorld(Android Test)

--res

Gradle Scripts

Chapter2 Android開發工具新接觸

工欲善其事,必先利其器

IDE Integrated Development Environment 內建開發環境

Eclipse vs Android Studio(2013年I/O大會)

http://www.androiddevtools.cn

Case sensitive completion

ADB指令

adb version

adb install -r F:\test.apk

adb push D:\test.apk /system/app/

adb push <local> <remote>

adb pull <remote> <local>

adb shell

adb remount

adb shell

rm *.apk

adb shell input keyevent 3

adb shell input touchscreen

adb shell input touchscreen swipe

pm/am

adb指令來源于\system\core\toolbox 和 \frameworks\base\cmds

Chapter3 Android控件架構與自定義控件詳解

Android中每個控件都會在界面中占得一塊矩形區域 ViewParent-ViewGroup/View 樹形結構

findViewById()深度優先周遊 setContentView()

Activity(PhoneWindow(DecorView(TitleView+ContentView))) 其中DecorView為根View WindowManagerService接收所有View的監聽事件

ContentView是一個id為content的FrameLayout TitleView一般為ActionBar Container requestWindowFeature(Window.FEATURE_NO_TITLE)要在setContentView()之前

ActivityManagerService進行Activity的生命周期回調

View的測量:onMeasure()

MeasureSpec是一個32位的int值 高2位為測量模式 低30位為測量的大小

測量模式:

    EXACTLY 适用于 android:layout_width="100"或者match_parent

    AT_MOST 适用于wrap_content

    UNSPECIFIED 适用于自定義View時 想多大就多大

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){

    //super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));

}

private int measureWidth(int measureSpec){

    int result = 100;

    int specMode = MeasureSpec.getMode(measureSpec);

    int specSize = MeasureSpec.getSize(measureSpec);

    if(specMode == MeasureSpec.EXACTLY){

        result = specSize;

    }else if(specMode == MeasureSpec.AT_MOST){

        result = Math.min(result, specSize);

    }

    return result;

}

View的繪制:onDraw()

Canvas對象 其它地方Canvas canvas = new Canvas(bitmap); canvas.drawXXX();

ViewGroup的測量:周遊子View

ViewGroup的繪制:dispatchDraw()

自定義View:擴充現有控件/組合實作控件/重寫View實作

onFinishInflate()/onSizeChanged()/onMeasure()/onLayout()/onDraw()/onTouchEvent()

定義屬性:res/values/attrs.xml <resources><declare-styleable name="TopBar"><attr name="title" format="string"/></declare-styleable></resources>

string|dimension|reference|color|boolean|enum

TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TopBar);

ta.recycle();

xmlns:custom="http://schemas.android.com/apk/res-auto"

重繪:invalidate();/postInvalidateDelayed(300);

自定義ViewGroup:int count = getChildCount(); View childView = getChildAt(i);

事件攔截處理機制

MotionEvent ACTION_DOWN ACTION_MOVE ACTION_UP

public boolean dispatchTouchEvent(MotionEvent ev);

public boolean onInterceptTouchEvent(MotionEvent ev);//View沒有此方法

public boolean onTouchEvent(MotionEvent ev);

流程:Adispatch->Aintercept->Bdispatch->Bintercept->Viewdispatch->ViewonTouch->BonTouch->AouTouch

誰攔截誰處理,處理完就回調

Chapter4 ListView使用技巧

public class DataAdapter extends BaseAdapter{

    private ArrayList<String> mDatas;

    private LayoutInflater mInflater;

    public DataAdapter(Context context){

        mDatas = new ArrayList<>();

        mInflater = LayoutInflater.from(context);

    }

    @Override

    public int getCount(){return mDatas.size();}

    @Override

    public Object getItem(int position){return mData.get(position);}

    @Override

    public long getItemId(int position){return position;}

    @Override

    public View getView(int position, View convertView, ViewGroup ){

        ViewHolder holder = null;

        if(convertView == null){

            convertView = mInflater.inflate(R.layout.item_content, null);

            holder = new ViewHolder();

            holder.content = (TextView)convertView.findViewById(R.id.content);

            convertView.setTag(holder);

        }else{

            holder = (ViewHolder)convertView.getTag();

        }

        holder.content.setText("use ViewHolder cache");

        return convertView;

    }

    public final class ViewHolder{

        public TextView content;

    }

}

設定分隔線:android:divider="@android:color/darker_grey" android:dividerHeight="10dp"

隐藏分隔線:android:divider="@null"

隐藏滾動條:android:scrollbars="none"

取消Item的點選效果:android:listSelector="#00000000" 或 android:listSelector="@android:color/transparent"

顯示在第幾項:listView.setSelection(N);listView.smoothScrollXX();

notifyDataSetChanged();

空ListView可以設定setEmptyView()來顯示内容為空時的提示

ListView的滑動監聽:GestureDetector/VelocityTracker onTouchListener/onScrollListener

firstVisibleItem/visibleItemCount/totalItemCount

overScrollBy()中maxOverScrollY改為一個數字就可以彈性十足了

自動顯示隐藏的ListView

//添加頭防止ActionBar引藏了第一個Item

View header = new View(this);

header.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, (int)getResources().getDimension(R.dimen_abc_action_bar_default_height_material)));

mListView.setHeader(header);

mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();//擷取最低滑動距離

View.OnTouchListener mOnTouchListener = new View.OnTouchListener(){……};//動畫用屬性動畫

不同布局的ListView

getItemViewType()/getViewTypeCount()

Chapter5 Android Scroll分析

滑動一個View本質上就是移動一個View改變其目前所處位置

Android坐标系:螢幕左上角(0, 0) 右 X正 下 Y正 getLocationOnScreen(int[] location); getRawX()/getRawY()

視圖坐标系:相對于父視圖 getX()/getY()

MotionEvent ACTION_DOWN/ACTION_UP/ACTION_MOVE/ACTION_CANCEL/ACTION_OUTSIDE/ACTION_POINTER_DOWN/ACTION_POINTER_UP

View提供的擷取坐标的方法:getTop()/getLeft()/getRight()/getBottom()

MotionEvent提供的方法:getX()/getY()/getRawX()/getRawY()

實作滑動的八種方法:

layout()/offsetLeftAndRight()和offsetTopAndBottom()/LayoutParams(getLayoutParams()/setLayoutParams)/scrollTo與scrollBy

Scroller/屬性動畫/ViewDragHelper(說好八種隻有七種還有一種,你想想)

Chapter6 Android繪圖機制與處理技巧

螢幕大小:螢幕對角線的長度,機關寸,如5.36寸

分辨率:螢幕的像素點數,720*1280指寬有720個像素點高有1280個像素點

PPI:Pixels Per Inch或DPI,Dots Per Inch 對角線像素點數除以螢幕大小

hdpi:240 / 480 X 800

dp/sp

public class DisplayUtil{

    public static int px2dip(Context context, float pxValue){

        final float scale = context.getResources().getDisplayMetrics().density;

        return (int)(pxValue / scale + 0.5f);

    }

    public static int dip2px(Context context, float dipValue){

        final float scale = context.getResources().getDisplayMetrics().density;

        return (int)(dipValue * scale + 0.5f);

    }

    public static int px2sp(Context context, float pxValue){

        final float fontScale = context.getResources().getDisplayMetrics().density;

        return (int)(pxValue / fontScale + 0.5f);

    }

    public static int sp2px(Context context, float spValue){

        final float fontScale = context.getResources().getDisplayMetrics().density;

        return (int)(spValue * fontScale + 0.5f);

    }

}

//TypedValue類也可以進行轉換

protected dp2px(int dp){

    return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());

}

protected sp2px(int sp){

    return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics());

}

2D繪圖:Canvas/Paint

Android XML繪圖:<bitmap/> <shape/> <layer-list/> <selector/>

Canvas.save()//類似儲存圖層

Canvas.restore()//類似合并圖層

Canvas.translate()//平移坐标原點

Canvas.rotate()//翻轉坐标原點

saveLayer()/saveLayerAlpha()/restore()/restoreToCount()

Bitmap位圖ARGB

色彩矩陣:ColorMatrix 4X5 一維數組存儲 矩陣乘法 RGBA 改變系數 改變偏移量

色調:setRotate()/飽和度:setSaturation()/亮度:setScale()

mImageView.setImageBitmap(ImageHelper.handleImageEffect());

paint.setColorFilter(new ColorMatrixColorFilter(imageMatrix));

像素點分析:

bitmap.getPixels(pixels, offset, stride, x, y, width, height);

bitmap.setPixels(newPx, 0, width, 0, 0, width, height);

Android圖像處理之圖形特效處理Matrix 3x3

Translate/Rotate/Scale/Skew

像素塊分析:drawBitmapMesh()

畫筆特效處理:PorterDuffXfermode

Shader着色器:BitmapShader/LinearGradient/RadialGradient/SweepGradient/ComposeShader

PathEffect

public class SurfaceViewTemplate extends SurfaceView implements SurfaceHolder.Callback, Runnable

surfaceCreated()/surfaceChanged()/surfaceDestroyed()/run()

private SurfaceHolder mHolder;

private Canvas mCanvas;

private boolean isDrawing;

mHolder = this.getHolder();

mHolder.addCallback(this);

mCanvas = mHolder.lockCanvas();

mHolder.unlockCanvasAndPost(mCanvas);

GenymotionChapter7 Android動畫機制與使用技巧

Frame Animation(drawable目錄裡frame.xml)/Tween Animation(anim目錄裡tween.xml)

Animation架構定義了AlphaAnimation/RotateAnimation/TranslateAnimation/ScaleAnimation四種動畫方式和AnimationSet動畫集合

AlphaAnimation aa = new AlphaAnimation(0, 1);

aa.setDuration(1000);

//aa.setAnimationListener(new Animation.AnimationListener(){……});

view.startAnimation(aa);

Animator架構AnimatorSet/ObjectAnimator

ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationX", 300);

animator.setDuration(300);

animator.start();

//操作對象必須有getter/setter

//translationX/translationY/rotation/rotationX/rotationY/scaleX/scaleY/pivotX/pivotY/x/y/alpha

private static class WrapperView{

    private View mTarget;

    public WrapperView(View target){

        mTarget = target;

    }

    public int getWidth(){

        return mTarget.getLayoutParams().width;

    }

    public void setWidth(int width){

        mTarget.setLayoutParams().width = width;

        mTarget.requestLayout();

    }

}

WrapperView wrapper = new WrapperView(mButton);

ObjectAnimator.ofInt(wrapper, "width", 500).setDuration(5000).start();

PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("translationX", 300);

PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("translationY", 300);

ObjectAnimator.ofPropertyValuesHolder(view, pvh1, pvh2).setDuration(3000).start();

ObjectAnimator繼承自ValueAnimator

ValueAnimator animator = ValueAnimator.ofFloat(0, 100);

animator.setTarget(view);

animator.setDuration(1000).start();

animator.addUpdateListener(new AnimatorUpdateListener(){……});

一個完整的動畫具有start repeat end cancel四個過程

animator.addListener(new AnimatorListener(){……});

animator.addListener(new AnimatorListenerAdapter(){……});

AnimatorSet set = new AnimatorSet();

set.setDuration(1000);

set.playTogether(animator1, animator2, animator3);

set.start();

//playTogether()/playSequentially()/before()/after()

animator目錄下animator.xml

<objectAnimator></objectAnimator>……

Animator animator = AnimatorInflater.loadAnimator(this, R.animator.scalex);

animator.setTarget(mView);

animator.start();

view.animate().alpha(0).y(300).setDuration(1000).widthStartAction(*).withEndAction(*).start();

Android布局動畫android:animateLayoutChanges="true"或者LayoutAnimationController

Interpolators插值器 定義動畫的變化速率 線性 加速度

自定義動畫:實作applyTransformation的邏輯并Override initialize() 主要是Matrix m = t.getMatrix();

SVG矢量動畫機制(5.X)Scalable Vector Graphics可伸縮矢量圖形 使用XML定義圖形 W3C标準

<path>标簽 指令:M/L/H/V/C/S/Q/T/A/Z 大寫絕對定位參照全局坐标系 小寫相對定位參照父容器會标系

http://editor.medhod.ac/

VectorDrawable/AnimatedVectorDrawable

group-path

<vector xmlns:android="http://schemas.android.com/apk/res/android"

    android:height="200dp"

    android:width="200dp"

    android:viewportHeight="100"

    android:viewportWidth="100">

    <group

        android:name="test"

        android:rotation="0">

        <path

            android:fillColor="@android:color/holo_blue_light"

            android:pathData="M 25 0 a 25 25 0 1, 0 50, 0" />

    </group>

</vector>

AnimatedVectorDrawable如同膠水一樣連接配接VectorDrawable和ObjectAnimator <animated-vector/>

(imageView.getDrawable()).start();開始動畫

線圖動畫 模拟三球儀 軌迹動畫

Chapter8 Activity與Activity調用棧分析

setContentView(View);

Running/Paused/Stopped/Killed

onCreate/onStart/onResume/onPause/onStop/onDestroy/onRestart

onSaveInstanceState()/onRestoreInstanceState

A task is a stack of activities.

android:laaunchMode/standard singleTop singleTask singleTop

Intent.FLAG_ACTIVITY_NEW_TASK

Intent.FLAG_ACTIVITY_SINGLE_TOP

Intent.FLAG_ACTIVITY_CLEAR_TOP

Intent.FLAG_ACTIVITY_NO_HISTORY

clearTaskOnLaunch/finishOnTaskLaunch/alwaysRetainTaskState

Chapter9 Android系統資訊與安全機制

系統的配置資訊:android.os.Build 和 SystemProperty

String board = Build.BOARD;

String os_version = System.getProperty("os.version");

system/build.prop /proc

PM/AM PackageManager/ActivityManager

ActivityInfo封裝了<activity/>和<receiver/>

ServiceInfo封裝了<service/>

ApplicationInfo封裝了<application/>

PackageInfo封裝了<manifest/>

ResolveInfo封裝了<intent/>

packages.xml檔案 /data/system/packages.xml

安全機制五道防線:代碼混淆proguard/AndroidManifest檔案權限聲明檢查/數字證書/UID通路權限控制/沙箱隔離

反編譯:

apktool/dex2jar/jd-gui/AndroidKiller

Chapter10 Android性能優化

UI優化

VSYNC信号觸發重新整理16ms一次 60fps

避免Overdraw

View測量、布局、繪制都是通過對View的周遊進行的

<include />重用Layout

<ViewStub />延遲加載Layout mViewStub = (ViewStub)findViewById(R.id.not_often_use);mViewStub.setVisibility(View.VISIBLE);或View inflateView = mViewStub.inflate();

Hierarchy Viewer

記憶體優化

Android應用沙箱機制 LMK

RAM

寄存器:速度最快,程式無法控制

棧:基本類型的資料和對象的引用

堆:new建立的對象和數組 由GC管理

靜态存儲區:一直存在的資料 如靜态資料變量

常量池:JVM為每個裝載的類型維護一個常量池

ActivityManager manager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);

int heapSize = manager.getLargeMemoryClass();

調用System.gc()隻是建議系統進行GC但不一定會被采納

Bitmap優化(常見于OOM):及時回收記憶體(bitmap.recycle())、圖檔緩存

任何Java類都将占用大約500位元組的記憶體空間 建立一個類的執行個體會消耗大約15位元組的記憶體

Lint/Memory Monitor/TraceView/Android Device Monitor/MAT/Dumpsys/

Debug.startMethodTracing("test");

Debug.stopMethodTracing();

Chapter11 搭建雲端伺服器

BAAS Backend As A Service

StackMob/Parse/Amazon/Kinvey/Bmob/原子雲/AVOS Cloud/百度Frontia/華為PowerApp

資料存儲 消息推送 檔案服務 API分析 應用統計 移動官網等

Chapter12 Android 5.X新特性

Material Design:紙墨光影紙紙、過渡動畫、大色塊

http://www.google.com/design/#resources

三種預設主題:

@android:style/Theme.Material

@android:style/Theme.Material.Light

@android:style/Theme.Material.Light.DarkActionBar

Color Palette

colorPrimary/colorPrimaryDark/textColorPrimary/navigationBarColor/windowBackground

色調各類:Vibrant/Vibrant dark/Vibrant light/Muted/Muted dark/Muted light

Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.test);

Palette.generateAsync(bmp, new Palette.PaletteAsyncListener(){

@Override

public void onGenerated(Palette palette){

Palette.Swatch vibrant = palette.getDarkVibrantSwatch();

getActionBar().setBackgroundDrawable(new ColorDrawable(vibrant.getRgb()));

getWindow().setStatusBarColor(vibrant.getRgb());

}

});

空間坐标系OXYZ

Z = elevation + translationZ

布局中:android:elevation="Xdp"

代碼中:view.setTranslation(X);view.animate().translationZ(X);

Tinting

android:tint="@android:color/holo_blue_bright"

android:tintMode="multiply"

Clipping

ViewOutlineProvider viewOutlineProvider = new ViewOutlineProvider(){

@Override

public void getOutline(View view, Outline outline){

outline.setOval(0, 0, view.getWidth(), view.getHeight());

}

};

v.setOutlineProvider(viewOutlineProvider);

RecyclerView

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder>{

private ArrayList<String> mData;

public RecyclerAdapter(){

mData = new ArrayList<>();

}

private OnItemClickListener itemClickListener;

  public void setOnItemClickListener(OnItemClickListener itemClickListener){

this.itemClickListener = itemClickListener;

}

public interface OnItemClickListener{

void onItemClick(View view, int position);

}

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

pulic TextView textView;

public ViewHolder(View itemView){

super(itemView);

textView = (TextView)itemView;

textView.setOnClickListener(this);

}

@Override

public void onClick(View v){

if(itemClickListener != null){

itemClickListener.onItemClick(v, getPosition());

}

}

}

@Override

public ViewHodler onCreateViewHolder(ViewGroup viewGroup, int i){

View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);

return new ViewHolder(v);

}

@Override

public void onBindViewHolder(ViewHolder viewHolder, int i){

viewHolder.textView.setText(mData.get(i));

}

@Override

public int getItemCount(){

return mData.size();

}

}

mRecyclerView.setLayoutManager(new LinearLayoutManager(this));

mRecyclerView.setItemAnimator(new DefaultItemAnimator());

mRecyclerView.setHasFixedSize(true);

CardView

xmlns:card_view="http://schemas.android.com/apk/res-auto"

card_view:cardBackgroundColor="@color/cardview_initial_background"

card_view:cardCornerRadius="10dp"

三種Transition類型:進入、退出、共享元素

Activity進入退出:explode/slide/fade

Activities共享元素:changeBounds/changeClipBounds/changeTransform/changeImageTransform

進入退出使用方法:

startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle());//ActivityA中

getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);//B

或者:<item name="android:windowContentTransitions">true</item>

getWindow().setEnterTransition(new Explode());//B

getWindow().setExitTransition(new Slide());

共享元素使用方法:

android:transitionName="XXX"

android:transitionName="XXX"

startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this, Pair.create(view. "share"), Pair.create(fab, "fab")).toBundle());//A

Ripple效果

android:background="?android:attr/selectableItemBackground"

android:background="?android:attr/selectableItemBackgroundBorderless"

<ripple

xmlns:android="http://schemas.android.com/apk/res/android"

android:color="@android:color/holo_blue_bright">

<item>

<shape>……</shape>

</item>

</ripple>

Animator animator = ViewAnimationUtils.createCircularReveal(oval, oval.getWidth()/2, oval.getHeight()/2, oval.getWidth(), 0);

animator.setInterpolator(new AccelerateDecelerateInterpolator());

animator.setDuration(2000);

animator.start();

狀态切換動畫

StateListAnimator

android:stateListAnimator="@drawable/anim_change"

selector的item中

<set>

<objectAnimator android:propertyName="rotationX"

android:duration="@android:integer/config_shortAnimTime"

android:valueTo="360"

android:valueType="floatType"/>

</set>

或者:AnimationInflater.loadStateListAnimator();View.setStateListAnimator();

Animated-selector

<animated-selector>

<item

android:id="@+id/state_on"

android:state_checked="true">

<bitmap android:src="@drawable/ic_done_anim_000"/>

<item>

<item

android:id="@+id/state_off">

<bitmap android:src="@drawable/ic_plus_anim_30"/>

<item>

<transition

android:fromId="@+id/state_on"

android:toId="@+id/state_off">

<animation-list>

<item android:duration="10"><bitmap android:src=""/></item>

</animation-list>

</transition>

……

</animated-selector>

ToolBar

ToolBar mToolBar = (ToolBar)findViewById(R.id.toolbar);

mToolBar.setLogo(R.drawable.ic_launcher);

mToolBar.setTitle("主标題");

mToolBar.setSubtitle("副标題");

setSupportActionBar(mToolBar);

DrawerLayout

配合使用

getSupportActionBar().setDisplayHomeAsUpEnable(true);

mDrawerLayout = (DrawerLayout)findViewById(R.id.drawer);

mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, mToolbar, R.string.abc_action_bar_home_description, R.string.abc_action_bar_home_description_format);

mDrawerToogle.syncState();

mDrawerLayout.setDrawerListener(mDrawerToggle);

基本Notification

NotificationBuilder builder = new NotificationBuilder(this);

PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);

builder.setContentIntent(pi);

builder.setContentTitle("test");

NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);

manager.notify(520, builder.build());

折疊Notification

RemoteViews contentView = new RemoteViews(getPackageame(), R.layout.notification);

contentView.setTextViewText(R.id.textView, "show me when collapsed");

notification.contentView = contentView;

RemoteViews expandedView = new RemoteViews(getPackageName(), R.layout.notification_expanded);

notification.bigContentView = expandedView;

懸挂Notification

builder.setContentText("test").setFullScreenIntent(pendingIntent, true);

不同等級

VISIBILITY_PRIVATE//沒有鎖屏時

VISIBILITY_PUBLIC//任何時候

VISIBILITY_SECRET//沒有PIN和PASSWORD等的情況下

builder.setVisibility(Notification.VISIBILITY_PUBLIC);

builder.setColor(Color.CYAN);

builder.setCategory(Notification.CATEGORY_MESSAGE);