ÄÚ´æÆª
1) Memory, GC, and Performance
ÖÚËùÖÜÖª£¬ÓëC/C++ÐèҪͨ¹ýÊÖ¶¯±àÂëÀ´ÉêÇëÒÔ¼°ÊÍ·ÅÄÚ´æÓÐËù²»Í¬£¬JavaÓµÓÐGCµÄ»úÖÆ¡£AndroidϵͳÀïÃæÓÐÒ»¸öGenerational
Heap MemoryµÄÄ£ÐÍ£¬ÏµÍ³»á¸ù¾ÝÄÚ´æÖв»Í¬µÄÄÚ´æÊý¾ÝÀàÐÍ·Ö±ðÖ´Ðв»Í¬µÄGC²Ù×÷¡£ÀýÈ磬×î½ü¸Õ·ÖÅäµÄ¶ÔÏó»á·ÅÔÚYoung
GenerationÇøÓò£¬Õâ¸öÇøÓòµÄ¶ÔÏóͨ³£¶¼ÊÇ»á¿ìËÙ±»´´½¨²¢ÇҺܿ챻Ïú»Ù»ØÊյģ¬Í¬Ê±Õâ¸öÇøÓòµÄGC²Ù×÷ËÙ¶ÈÒ²ÊDZÈOld
GenerationÇøÓòµÄGC²Ù×÷Ëٶȸü¿ìµÄ¡£

³ýÁËËٶȲîÒìÖ®Í⣬ִÐÐGC²Ù×÷µÄʱºò£¬ËùÓÐÏ̵߳ÄÈκβÙ×÷¶¼»áÐèÒªÔÝÍ££¬µÈ´ýGC²Ù×÷Íê³ÉÖ®ºó£¬ÆäËû²Ù×÷²ÅÄܹ»¼ÌÐøÔËÐС£

ͨ³£À´Ëµ£¬µ¥¸öµÄGC²¢²»»áÕ¼ÓÃÌ«¶àʱ¼ä£¬µ«ÊÇ´óÁ¿²»Í£µÄGC²Ù×÷Ôò»áÏÔÖøÕ¼ÓÃÖ¡¼ä¸ôʱ¼ä(16ms)¡£Èç¹ûÔÚÖ¡¼ä¸ôʱ¼äÀïÃæ×öÁ˹ý¶àµÄGC²Ù×÷£¬ÄÇô×ÔÈ»ÆäËûÀàËÆ¼ÆË㣬äÖȾµÈ²Ù×÷µÄ¿ÉÓÃʱ¼ä¾Í±äµÃÉÙÁË¡£
2) Memory Monitor Walkthrough
Android StudioÖеÄMemory Monitor¿ÉÒԺܺõذïÖúÎÒÃDz鿴³ÌÐòµÄÄÚ´æÊ¹ÓÃÇé¿ö¡£



3) Memory Leaks
ÄÚ´æÐ¹Â©±íʾµÄÊDz»ÔÙÓõ½µÄ¶ÔÏóÒòΪ±»´íÎóÒýÓöøÎÞ·¨½øÐлØÊÕ¡£

·¢ÉúÄÚ´æÐ¹Â©»áµ¼ÖÂMemory GenerationÖеÄÊ£Óà¿ÉÓÃHeap SizeÔ½À´Ô½Ð¡£¬ÕâÑù»áµ¼ÖÂÆµ·±´¥·¢GC£¬¸ü½øÒ»²½ÒýÆðÐÔÄÜÎÊÌâ¡£
¾ÙÀýÄÚ´æÐ¹Â©£¬ÏÂÃæinit()·½·¨À´×Ôij¸ö×Ô¶¨ÒåView£º
private void init() { ListenerCollector collector = new ListenerCollector(); collector.setListener(this, mListener); } |
ÉÏÃæµÄÀý×ÓÈÝÒ×´æÔÚÄÚ´æÐ¹Â©£¬Èç¹ûactivityÒòΪÉ豸·×ª¶øÖØÐ´´½¨£¬×Ô¶¨ÒåµÄView»á×Ô¶¯ÖØÐ°Ñд´½¨³öÀ´µÄmListener¸ø°ó¶¨µ½ListenerCollectorÖУ¬µ«Êǵ±activity±»Ïú»ÙµÄʱºò£¬mListenerÈ´ÎÞ·¨±»»ØÊÕÁË¡£
4) Heap Viewer Walkthrough
ÏÂͼÑÝʾÁËAndroid ToolsÀïÃæµÄHeap ViewerµÄ¹¦ÄÜ£¬ÎÒÃÇ¿ÉÒÔ¿´µ½µ±Ç°½ø³ÌÖеÄHeap
SizeµÄÇé¿ö£¬·Ö±ðÓÐÄÄЩÀàÐ͵ÄÊý¾Ý£¬Õ¼±ÈÊǶàÉÙ¡£

5) Understanding Memory Churn
Memory ChurnÄÚ´æ¶¶¶¯£¬ÄÚ´æ¶¶¶¯ÊÇÒòΪÔÚ¶Ìʱ¼äÄÚ´óÁ¿µÄ¶ÔÏó±»´´½¨ÓÖÂíÉϱ»ÊÍ·Å¡£Ë²¼ä²úÉú´óÁ¿µÄ¶ÔÏó»áÑÏÖØÕ¼ÓÃYoung
GenerationµÄÄÚ´æÇøÓò£¬µ±´ïµ½·§Öµ£¬Ê£Óà¿Õ¼ä²»¹»µÄʱºò£¬»á´¥·¢GC´Ó¶øµ¼Ö¸ղúÉúµÄ¶ÔÏóÓֺܿ챻»ØÊÕ¡£¼´Ê¹Ã¿´Î·ÖÅäµÄ¶ÔÏóÕ¼ÓÃÁ˺ÜÉÙµÄÄڴ棬µ«ÊÇËûÃǵþ¼ÓÔÚÒ»Æð»áÔö¼ÓHeapµÄѹÁ¦£¬´Ó¶ø´¥·¢¸ü¶àÆäËûÀàÐ͵ÄGC¡£Õâ¸ö²Ù×÷ÓпÉÄÜ»áÓ°Ïìµ½Ö¡ÂÊ£¬²¢Ê¹µÃÓû§¸ÐÖªµ½ÐÔÄÜÎÊÌâ¡£

½â¾öÉÏÃæµÄÎÊÌâÓмò½àÖ±¹Û·½·¨£¬Èç¹ûÄãÔÚMemory MonitorÀïÃæ²é¿´µ½¶Ìʱ¼ä·¢ÉúÁ˶à´ÎÄÚ´æµÄÕǵø£¬ÕâÒâζןÜÓпÉÄÜ·¢ÉúÁËÄÚ´æ¶¶¶¯¡£

ͬʱÎÒÃÇ»¹¿ÉÒÔͨ¹ýAllocation TrackerÀ´²é¿´ÔÚ¶Ìʱ¼äÄÚ£¬Í¬Ò»¸öÕ»Öв»¶Ï½ø³öµÄÏàͬ¶ÔÏó¡£ÕâÊÇÄÚ´æ¶¶¶¯µÄµäÐÍÐźÅÖ®Ò»¡£
µ±Äã´óÖ¶¨Î»ÎÊÌâÖ®ºó£¬½ÓÏÂÈ¥µÄÎÊÌâÐÞ¸´Ò²¾ÍÏÔµÃÏà¶ÔÖ±½Ó¼òµ¥ÁË¡£ÀýÈ磬ÄãÐèÒª±ÜÃâÔÚforÑ»·ÀïÃæ·ÖÅä¶ÔÏóÕ¼ÓÃÄڴ棬ÐèÒª³¢Ê԰ѶÔÏóµÄ´´½¨ÒƵ½Ñ»·ÌåÖ®Í⣬×Ô¶¨ÒåViewÖеÄonDraw·½·¨Ò²ÐèÒªÒýÆð×¢Ò⣬ÿ´ÎÆÁÄ»·¢Éú»æÖÆÒÔ¼°¶¯»Ö´Ðйý³ÌÖУ¬onDraw·½·¨¶¼»á±»µ÷Óõ½£¬±ÜÃâÔÚonDraw·½·¨ÀïÃæÖ´Ðи´ÔӵIJÙ×÷£¬±ÜÃâ´´½¨¶ÔÏó¡£¶ÔÓÚÄÇЩÎÞ·¨±ÜÃâÐèÒª´´½¨¶ÔÏóµÄÇé¿ö£¬ÎÒÃÇ¿ÉÒÔ¿¼ÂǶÔÏó³ØÄ£ÐÍ£¬Í¨¹ý¶ÔÏó³ØÀ´½â¾öƵ·±´´½¨ÓëÏú»ÙµÄÎÊÌ⣬µ«ÊÇÕâÀïÐèҪעÒâ½áÊøÊ¹ÓÃÖ®ºó£¬ÐèÒªÊÖ¶¯ÊͷŶÔÏó³ØÖеĶÔÏó¡£
6) Allocation Tracker
¹ØÓÚAllocation Tracker¹¤¾ßµÄʹÓ㬲»Õ¹¿ªÁË£¬²Î¿¼ÏÂÃæµÄÁ´½Ó£º
http://developer.android.com/tools/debugging/ddms.html#alloc
http://android-developers.blogspot.com/2009/02/track-memory-allocations.html
7) Improve Your Code To Reduce Churn
ÏÂÃæÑÝʾһ¸öÀý×Ó£¬ÈçºÎͨ¹ýÐ޸ĴúÂëÀ´±ÜÃâÄÚ´æ¶¶¶¯¡£ÓÅ»¯Ö®Ç°µÄÄÚ´æ¼ì²âͼ£º

¶¨Î»´úÂëÖ®ºó£¬ÐÞ¸´ÁËStringÆ´½ÓµÄÎÊÌ⣺

ÓÅ»¯Ö®ºóµÄÄÚ´æ¼à²âͼ£º

8) Recap
ÉÏÃæÌáµ½ÁËÈýÖÖ²âÁ¿ÄÚ´æµÄ¹¤¾ß£¬ÏÂÃæÔÙ¼òÒª¸ÅÀ¨Ò»ÏÂËûÃǸ÷×ÔµÄÌØµã£º
1.Memory Monitor£º¸ú×ÙÕû¸öappµÄÄÚ´æ±ä»¯Çé¿ö¡£
2.Heap Viewer£º²é¿´µ±Ç°ÄÚ´æ¿ìÕÕ£¬±ãÓڶԱȷÖÎöÄÄЩ¶ÔÏóÓпÉÄÜ·¢ÉúÁËй©¡£
3.Allocation Tracker£º×·×ÙÄÚ´æ¶ÔÏóµÄÀ´Ô´¡£
µçÁ¿Æª
1) Understanding Battery Drain
ÊÖ»ú¸÷¸öÓ²¼þÄ£¿éµÄºÄµçÁ¿ÊDz»Ò»ÑùµÄ£¬ÓÐЩģ¿é·Ç³£ºÄµç£¬¶øÓÐЩģ¿éÔòÏà¶ÔÏԵúĵçÁ¿Ð¡ºÜ¶à¡£

µçÁ¿ÏûºÄµÄ¼ÆËãÓëͳ¼ÆÊÇÒ»¼þÂé·³¶øÇÒì¶ÜµÄÊÂÇ飬¼Ç¼µçÁ¿ÏûºÄ±¾ÉíÒ²ÊÇÒ»¸ö·ÑµçÁ¿µÄÊÂÇ顣Ψһ¿ÉÐеķ½°¸ÊÇʹÓõÚÈý·½¼à²âµçÁ¿µÄÉ豸£¬ÕâÑù²ÅÄܹ»»ñÈ¡µ½ÕæÊµµÄµçÁ¿ÏûºÄ¡£
µ±É豸´¦ÓÚ´ý»ú״̬ʱÏûºÄµÄµçÁ¿ÊǼ«Éٵģ¬ÒÔN5ΪÀý£¬´ò¿ª·ÉÐÐģʽ£¬¿ÉÒÔ´ý»ú½Ó½ü1¸öÔ¡£¿ÉÊǵãÁÁÆÁÄ»£¬Ó²¼þ¸÷¸öÄ£¿é¾ÍÐèÒª¿ªÊ¼¹¤×÷£¬Õâ»áÐèÒªÏûºÄºÜ¶àµçÁ¿¡£
ʹÓÃWakeLock»òÕßJobScheduler»½ÐÑÉ豸´¦Àí¶¨Ê±µÄÈÎÎñÖ®ºó£¬Ò»¶¨Òª¼°Ê±ÈÃÉ豸»Øµ½³õʼ״̬¡£Ã¿´Î»½ÐÑ·äÎÑÐźŽøÐÐÊý¾Ý´«µÝ£¬¶¼»áÏûºÄºÜ¶àµçÁ¿£¬Ëü±ÈWiFiµÈ²Ù×÷¸ü¼ÓµÄºÄµç¡£

2) Battery Historian
Battery HistorianÊÇAndroid 5.0¿ªÊ¼ÒýÈëµÄÐÂAPI¡£Í¨¹ýÏÂÃæµÄÖ¸Á¿ÉÒԵõ½É豸ÉϵĵçÁ¿ÏûºÄÐÅÏ¢£º
$ adb shell dumpsys batterystats > xxx.txt //µÃµ½Õû¸öÉ豸µÄµçÁ¿ÏûºÄÐÅÏ¢ $ adb shell dumpsys batterystats > com.package.name > xxx.txt //µÃµ½Ö¸¶¨appÏà¹ØµÄµçÁ¿ÏûºÄÐÅÏ¢ |
µÃµ½ÁËÔʼµÄµçÁ¿ÏûºÄÊý¾ÝÖ®ºó£¬ÎÒÃÇÐèҪͨ¹ýGoogle±àдµÄÒ»¸öpython½Å±¾°ÑÊý¾ÝÐÅϢת»»³É¿É¶ÁÐÔ¸üºÃµÄhtmlÎļþ£º
$ python historian.py xxx.txt > xxx.html |
´ò¿ªÕâ¸öת»»¹ýºóµÄhtmlÎļþ£¬¿ÉÒÔ¿´µ½ÀàËÆTraceViewÉú³ÉµÄÁбíÊý¾Ý£¬ÕâÀïµÄÊý¾ÝÐÅÏ¢Á¿ºÜ´ó£¬ÕâÀï¾Í²»Õ¹¿ªÁË¡£

3) Track Battery Status & Battery Manager
ÎÒÃÇ¿ÉÒÔͨ¹ýÏÂÃæµÄ´úÂëÀ´»ñÈ¡ÊÖ»úµÄµ±Ç°³äµç״̬£º
// It is very easy to subscribe to changes to the battery state, but you can get the current // state by simply passing null in as your receiver. Nifty, isn't that? IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); Intent batteryStatus = this.registerReceiver(null, filter); int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); boolean acCharge = (chargePlug == BatteryManager.BATTERY_PLUGGED_AC); if (acCharge) { Log.v(LOG_TAG,¡°The phone is charging!¡±); } |
ÔÚÉÏÃæµÄÀý×ÓÑÝʾÁËÈçºÎÁ¢¼´»ñÈ¡µ½ÊÖ»úµÄ³äµç״̬£¬µÃµ½³äµç״̬ÐÅÏ¢Ö®ºó£¬ÎÒÃÇ¿ÉÒÔÓÐÕë¶ÔÐԵĶԲ¿·Ö´úÂë×öÓÅ»¯¡£±ÈÈçÎÒÃÇ¿ÉÒÔÅжÏÖ»Óе±Ç°ÊÖ»úΪAC³äµç״̬ʱ
²ÅÈ¥Ö´ÐÐһЩ·Ç³£ºÄµçµÄ²Ù×÷¡£
/** * This method checks for power by comparing the current battery state against all possible * plugged in states. In this case, a device may be considered plugged in either by USB, AC, or * wireless charge. (Wireless charge was introduced in API Level 17.) */ private boolean checkForPower() { // It is very easy to subscribe to changes to the battery state, but you can get the current // state by simply passing null in as your receiver. Nifty, isn't that? IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); Intent batteryStatus = this.registerReceiver(null, filter); // There are currently three ways a device can be plugged in. We should check them all. int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); boolean usbCharge = (chargePlug == BatteryManager.BATTERY_PLUGGED_USB); boolean acCharge = (chargePlug == BatteryManager.BATTERY_PLUGGED_AC); boolean wirelessCharge = false; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { wirelessCharge = (chargePlug == BatteryManager.BATTERY_PLUGGED_WIRELESS); } return (usbCharge || acCharge || wirelessCharge); } |
4) Wakelock and Battery Drain
¸ßЧµÄ±£Áô¸ü¶àµÄµçÁ¿Óë²»¶Ï´ÙʹÓû§Ê¹ÓÃÄãµÄApp»áÏûºÄµçÁ¿£¬ÕâÊÇì¶ÜµÄÑ¡ÔñÌâ¡£²»¹ýÎÒÃÇ¿ÉÒÔʹÓÃһЩ¸üºÃµÄ°ì·¨À´Æ½ºâÁ½Õß¡£
¼ÙÉèÄãµÄÊÖ»úÀïÃæ×°ÁË´óÁ¿µÄÉç½»ÀàÓ¦Ó㬼´Ê¹ÊÖ»ú´¦ÓÚ´ý»ú״̬£¬Ò²»á¾³£±»ÕâЩӦÓû½ÐÑÓÃÀ´¼ì²éͬ²½ÐµÄÊý¾ÝÐÅÏ¢¡£Android»á²»¶Ï¹Ø±Õ¸÷ÖÖÓ²¼þÀ´ÑÓ³¤ÊÖ»úµÄ´ý»úʱ¼ä£¬Ê×ÏÈÆÁÄ»»áÖ𽥱䰵ֱÖÁ¹Ø±Õ£¬È»ºóCPU½øÈë˯Ãߣ¬ÕâÒ»ÇвÙ×÷¶¼ÊÇΪÁ˽ÚÔ¼±¦¹óµÄµçÁ¿×ÊÔ´¡£µ«ÊǼ´Ê¹ÔÚÕâÖÖ˯Ãß״̬Ï£¬´ó¶àÊýÓ¦Óû¹Êǻ᳢ÊÔ½øÐй¤×÷£¬ËûÃǽ«²»¶ÏµÄ»½ÐÑÊÖ»ú¡£Ò»¸ö×î¼òµ¥µÄ»½ÐÑÊÖ»úµÄ·½·¨ÊÇʹÓÃPowerManager.WakeLockµÄAPIÀ´±£³ÖCPU¹¤×÷²¢·ÀÖ¹ÆÁÄ»±ä°µ¹Ø±Õ¡£ÕâʹµÃÊÖ»ú¿ÉÒÔ±»»½ÐÑ£¬Ö´Ðй¤×÷£¬È»ºó»Øµ½Ë¯Ãß״̬¡£ÖªµÀÈçºÎ»ñÈ¡WakeLockÊǼòµ¥µÄ£¬¿ÉÊǼ°Ê±ÊÍ·ÅWakeLockÒ²ÊǷdz£ÖØÒªµÄ£¬²»Ç¡µ±µÄʹÓÃWakeLock»áµ¼ÖÂÑÏÖØ´íÎó¡£ÀýÈçÍøÂçÇëÇóµÄÊý¾Ý·µ»ØÊ±¼ä²»È·¶¨£¬µ¼Ö±¾À´Ö»ÐèÒª10sµÄÊÂÇéÒ»Ö±µÈ´ýÁË1¸öСʱ£¬ÕâÑù»áʹµÃµçÁ¿°×°×ÀË·ÑÁË¡£ÕâÒ²ÊÇΪºÎʹÓôø³¬Ê±²ÎÊýµÄwakelock.acquice()·½·¨ÊǺܹؼüµÄ¡£
µ«Êǽö½öÉèÖó¬Ê±²¢²»×ã¹»½â¾öÎÊÌ⣬ÀýÈçÉèÖö೤µÄ³¬Ê±±È½ÏºÏÊÊ£¿Ê²Ã´Ê±ºò½øÐÐÖØÊԵȵȣ¿½â¾öÉÏÃæµÄÎÊÌ⣬ÕýÈ·µÄ·½Ê½¿ÉÄÜÊÇʹÓ÷Ǿ«×¼¶¨Ê±Æ÷¡£Í¨³£Çé¿öÏ£¬ÎÒÃÇ»áÉ趨һ¸öʱ¼ä½øÐÐij¸ö²Ù×÷£¬µ«ÊǶ¯Ì¬ÐÞ¸ÄÕâ¸öʱ¼äÒ²Ðí»á¸üºÃ¡£ÀýÈ磬Èç¹ûÓÐÁíÍâÒ»¸ö³ÌÐòÐèÒª±ÈÄãÉ趨µÄʱ¼äÍí5·ÖÖÓ»½ÐÑ£¬×îºÃÄܹ»µÈµ½ÄǸöʱºò£¬Á½¸öÈÎÎñÀ¦°óÒ»Æðͬʱ½øÐУ¬Õâ¾ÍÊǷǾ«È·¶¨Ê±Æ÷µÄºËÐŤ×÷ÔÀí¡£ÎÒÃÇ¿ÉÒÔ¶¨ÖƼƻ®µÄÈÎÎñ£¬¿ÉÊÇϵͳÈç¹û¼ì²âµ½Ò»¸ö¸üºÃµÄʱ¼ä£¬Ëü¿ÉÒÔÍÆ³ÙÄãµÄÈÎÎñ£¬ÒÔ½ÚÊ¡µçÁ¿ÏûºÄ¡£

ÕâÕýÊÇJobScheduler APIËù×öµÄÊÂÇé¡£Ëü»á¸ù¾Ýµ±Ç°µÄÇé¿öÓëÈÎÎñ£¬×éºÏ³öÀíÏëµÄ»½ÐÑʱ¼ä£¬ÀýÈçµÈµ½ÕýÔÚ³äµç»òÕßÁ¬½Óµ½WiFiµÄʱºò£¬»òÕß¼¯ÖÐÈÎÎñÒ»ÆðÖ´ÐС£ÎÒÃÇ¿ÉÒÔͨ¹ýÕâ¸öAPIʵÏֺܶàÃâ·ÑµÄµ÷¶ÈËã·¨¡£
5) Network and Battery Drain
ÏÂÃæÄÚÈÝÀ´×Ô¹Ù·½TrainingÎĵµÖиßЧÏÂÔØÕ½ڹØÓÚÊÖ»ú(Radio)·äÎÑÐźŶԵçÁ¿ÏûºÄµÄ½éÉÜ¡£
ͨ³£Çé¿öÏ£¬Ê¹ÓÃ3GÒÆ¶¯ÍøÂç´«ÊäÊý¾Ý£¬µçÁ¿µÄÏûºÄÓÐÈýÖÖ״̬£º
1.Full power: ÄÜÁ¿×î¸ßµÄ״̬£¬Òƶ¯ÍøÂçÁ¬½Ó±»¼¤»î£¬ÔÊÐíÉ豸ÒÔ×î´óµÄ´«ÊäËÙÂʽøÐвÙ×÷¡£
2.Low power: Ò»ÖÖÖмä״̬£¬¶ÔµçÁ¿µÄÏûºÄ²î²»¶àÊÇFull power״̬ϵÄ50%¡£
3.Standby: ×îµÍµÄ״̬£¬Ã»ÓÐÊý¾ÝÁ¬½ÓÐèÒª´«Ê䣬µçÁ¿ÏûºÄ×îÉÙ¡£
ÏÂͼÊÇÒ»¸öµäÐ͵Ä3G Radio State MachineµÄͼʾ(À´×ÔAT&T£¬ÏêÇéÇëµã»÷ÕâÀï)£º

×ÜÖ®£¬ÎªÁ˼õÉÙµçÁ¿µÄÏûºÄ£¬ÔÚ·äÎÑÒÆ¶¯ÍøÂçÏ£¬×îºÃ×öµ½ÅúÁ¿Ö´ÐÐÍøÂçÇëÇ󣬾¡Á¿±ÜÃâÆµ·±µÄ¼ä¸ôÍøÂçÇëÇó¡£
ͨ¹ýÇ°ÃæÑ§Ï°µ½µÄBattery HistorianÎÒÃÇ¿ÉÒԵõ½É豸µÄµçÁ¿ÏûºÄÊý¾Ý£¬Èç¹ûÊý¾ÝÖеÄÒÆ¶¯·äÎÑÍøÂç(Mobile
Radio)µçÁ¿ÏûºÄ³ÊÏÖÏÂÃæµÄÇé¿ö£¬¼ä¸ôºÜС£¬ÓÖÆµ·±¶Ï¶ÏÐøÐøµÄ³öÏÖ£¬ËµÃ÷µçÁ¿ÏûºÄÐÔÄܺܲ»ºÃ£º

¾¹ýÓÅ»¯Ö®ºó£¬Èç¹û³ÊÏÖÏÂÃæµÄͼʾ£¬ËµÃ÷µçÁ¿ÏûºÄµÄÐÔÄÜÊÇÁ¼ºÃµÄ£º

ÁíÍâWiFiÁ¬½ÓÏ£¬ÍøÂç´«ÊäµÄµçÁ¿ÏûºÄÒª±ÈÒÆ¶¯ÍøÂçÉٺܶ࣬Ӧ¸Ã¾¡Á¿¼õÉÙÒÆ¶¯ÍøÂçϵÄÊý¾Ý´«Ê䣬¶àÔÚWiFi»·¾³Ï´«ÊäÊý¾Ý¡£

ÄÇôÈçºÎ²ÅÄܹ»°ÑÈÎÎñ»º´æÆðÀ´£¬×öµ½ÅúÁ¿»¯Ö´ÐÐÄØ£¿ÏÂÃæ¾ÍÂÖµ½Job Scheduler³ö³¡ÁË¡£
6) Using Job Scheduler
ʹÓÃJob Scheduler£¬Ó¦ÓÃÐèÒª×öµÄÊÂÇé¾ÍÊÇÅжÏÄÄЩÈÎÎñÊDz»½ô¼±µÄ£¬¿ÉÒÔ½»¸øJob SchedulerÀ´´¦Àí£¬Job
Scheduler¼¯Öд¦ÀíÊÕµ½µÄÈÎÎñ£¬Ñ¡ÔñºÏÊʵÄʱ¼ä£¬ºÏÊʵÄÍøÂ磬ÔÙÒ»Æð½øÐÐÖ´ÐС£
ÏÂÃæÊÇʹÓÃJob SchedulerµÄÒ»¶Î¼òҪʾÀý£¬ÐèÒªÏÈÓÐÒ»¸öJobService£º
public class MyJobService extends JobService { private static final String LOG_TAG = "MyJobService"; @Override public void onCreate() { super.onCreate(); Log.i(LOG_TAG, "MyJobService created"); } @Override public void onDestroy() { super.onDestroy(); Log.i(LOG_TAG, "MyJobService destroyed"); } @Override public boolean onStartJob(JobParameters params) { // This is where you would implement all of the logic for your job. Note that this runs // on the main thread, so you will want to use a separate thread for asynchronous work // (as we demonstrate below to establish a network connection). // If you use a separate thread, return true to indicate that you need a "reschedule" to // return to the job at some point in the future to finish processing the work. Otherwise, // return false when finished. Log.i(LOG_TAG, "Totally and completely working on job " + params.getJobId()); // First, check the network, and then attempt to connect. if (isNetworkConnected()) { new SimpleDownloadTask() .execute(params); return true; } else { Log.i(LOG_TAG, "No connection on job " + params.getJobId() + "; sad face"); } return false; } @Override
public boolean onStopJob(JobParameters params) { // Called if the job must be stopped before jobFinished() has been called. This may // happen if the requirements are no longer being met, such as the user no longer // connecting to WiFi, or the device no longer being idle. Use this callback to resolve // anything that may cause your application to misbehave from the job being halted. // Return true if the job should be rescheduled based on the retry criteria specified // when the job was created or return false to drop the job. Regardless of the value // returned, your job must stop executing. Log.i(LOG_TAG, "Whelp, something changed, so I'm calling it on job " + params.getJobId()); return false; } /** * Determines if the device is currently online. */ private boolean isNetworkConnected() { ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); return (networkInfo != null && networkInfo.isConnected()); } /** * Uses AsyncTask to create a task away from the main UI thread. This task creates a * HTTPUrlConnection, and then downloads the contents of the webpage as an InputStream. * The InputStream is then converted to a String, which is logged by the * onPostExecute() method. */ private class SimpleDownloadTask extends AsyncTask<JobParameters, Void, String> { protected JobParameters mJobParam; @Override protected String doInBackground(JobParameters... params) { // cache system provided job requirements mJobParam = params[0]; try { InputStream is = null; // Only display the first 50 characters of the retrieved web page content. int len = 50; URL url = new URL("https://www.google.com"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(10000); //10sec conn.setConnectTimeout(15000); //15sec conn.setRequestMethod("GET"); //Starts the query conn.connect(); int response = conn.getResponseCode(); Log.d(LOG_TAG, "The response is: " + response); is = conn.getInputStream(); // Convert the input stream to a string Reader reader = null; reader = new InputStreamReader(is, "UTF-8"); char[] buffer = new char[len]; reader.read(buffer); return new String(buffer); } catch (IOException e) { return "Unable to retrieve web page."; } } @Override protected void onPostExecute(String result) { jobFinished(mJobParam, false); Log.i(LOG_TAG, result); } } } |
È»ºóÄ£Äâͨ¹ýµã»÷Button´¥·¢N¸öÈÎÎñ£¬½»¸øJobServiceÀ´´¦Àí£º
public class FreeTheWakelockActivity extends ActionBarActivity { public static final String LOG_TAG = "FreeTheWakelockActivity"; TextView mWakeLockMsg; ComponentName mServiceComponent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_wakelock); mWakeLockMsg = (TextView) findViewById(R.id.wakelock_txt); mServiceComponent = new ComponentName(this, MyJobService.class); Intent startServiceIntent = new Intent(this, MyJobService.class); startService(startServiceIntent); Button theButtonThatWakelocks = (Button) findViewById(R.id.wakelock_poll); theButtonThatWakelocks.setText(R.string.poll_server_button); theButtonThatWakelocks.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { pollServer(); } }); } /** * This method polls the server via the JobScheduler API. By scheduling the job with this API, * your app can be confident it will execute, but without the need for a wake lock. Rather, the * API will take your network jobs and execute them in batch to best take advantage of the * initial network connection cost. * * The JobScheduler API works through a background service. In this sample, we have * a simple service in MyJobService to get you started. The job is scheduled here in * the activity, but the job itself is executed in MyJobService in the startJob() method. For * example, to poll your server, you would create the network connection, send your GET * request, and then process the response all in MyJobService. This allows the JobScheduler API * to invoke your logic without needed to restart your activity. * * For brevity in the sample, we are scheduling the same job several times in quick succession, * but again, try to consider similar tasks occurring over time in your application that can * afford to wait and may benefit from batching. */ public void pollServer() { JobScheduler scheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); for (int i=0; i<10; i++) { JobInfo jobInfo = new JobInfo.Builder(i, mServiceComponent) .setMinimumLatency(5000) // 5 seconds .setOverrideDeadline(60000) // 60 seconds (for brevity in the sample) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) // WiFi or data connections .build(); mWakeLockMsg.append("Scheduling job " + i + "!\n"); scheduler.schedule(jobInfo); } } } |
|