1616
1717package com .tencent .tinker .lib .service ;
1818
19+ import android .annotation .TargetApi ;
1920import android .app .IntentService ;
2021import android .app .Notification ;
2122import android .app .Service ;
23+ import android .app .job .JobInfo ;
24+ import android .app .job .JobParameters ;
25+ import android .app .job .JobScheduler ;
26+ import android .app .job .JobService ;
27+ import android .content .ComponentName ;
2228import android .content .Context ;
2329import android .content .Intent ;
30+ import android .os .AsyncTask ;
2431import android .os .Build ;
2532import android .os .IBinder ;
33+ import android .os .PersistableBundle ;
2634import android .os .SystemClock ;
35+ import android .support .annotation .Nullable ;
2736
2837import com .tencent .tinker .lib .patch .AbstractPatch ;
2938import com .tencent .tinker .lib .tinker .Tinker ;
3342import com .tencent .tinker .loader .shareutil .ShareIntentUtil ;
3443
3544import java .io .File ;
45+ import java .lang .ref .WeakReference ;
3646
3747/**
3848 * Created by zhangshaowen on 16/3/14.
3949 */
40- public class TinkerPatchService extends IntentService {
50+ public class TinkerPatchService {
4151 private static final String TAG = "Tinker.TinkerPatchService" ;
4252
4353 private static final String PATCH_PATH_EXTRA = "patch_path_extra" ;
@@ -47,19 +57,27 @@ public class TinkerPatchService extends IntentService {
4757 private static int notificationId = ShareConstants .TINKER_PATCH_SERVICE_NOTIFICATION ;
4858 private static Class <? extends AbstractResultService > resultServiceClass = null ;
4959
50- /**
51- * Creates an IntentService. Invoked by your subclass's constructor.
52- */
53- public TinkerPatchService () {
54- super (TinkerPatchService .class .getSimpleName ());
55- }
56-
5760 public static void runPatchService (Context context , String path ) {
5861 try {
59- Intent intent = new Intent (context , TinkerPatchService .class );
60- intent .putExtra (PATCH_PATH_EXTRA , path );
61- intent .putExtra (RESULT_CLASS_EXTRA , resultServiceClass .getName ());
62- context .startService (intent );
62+ if (Build .VERSION .SDK_INT < 21 ) {
63+ Intent intent = new Intent (context , IntentServiceRunner .class );
64+ intent .putExtra (PATCH_PATH_EXTRA , path );
65+ intent .putExtra (RESULT_CLASS_EXTRA , resultServiceClass .getName ());
66+ context .startService (intent );
67+ } else {
68+ final JobInfo .Builder jobInfoBuilder = new JobInfo .Builder (
69+ 1 , new ComponentName (context , JobServiceRunner .class )
70+ );
71+ final PersistableBundle extras = new PersistableBundle ();
72+ extras .putString (PATCH_PATH_EXTRA , path );
73+ extras .putString (RESULT_CLASS_EXTRA , resultServiceClass .getName ());
74+ jobInfoBuilder .setExtras (extras );
75+ jobInfoBuilder .setMinimumLatency (1 );
76+ final JobScheduler jobScheduler = (JobScheduler ) context .getSystemService (Context .JOB_SCHEDULER_SERVICE );
77+ if (jobScheduler .schedule (jobInfoBuilder .build ()) != JobScheduler .RESULT_SUCCESS ) {
78+ TinkerLog .e (TAG , "start patch job service fail." );
79+ }
80+ }
6381 } catch (Throwable throwable ) {
6482 TinkerLog .e (TAG , "start patch service fail, exception:" + throwable );
6583 }
@@ -90,6 +108,14 @@ public static String getPatchResultExtra(Intent intent) {
90108 return ShareIntentUtil .getStringExtra (intent , RESULT_CLASS_EXTRA );
91109 }
92110
111+ public static Class <? extends Service > getRealRunnerClass () {
112+ if (Build .VERSION .SDK_INT < 21 ) {
113+ return IntentServiceRunner .class ;
114+ } else {
115+ return JobServiceRunner .class ;
116+ }
117+ }
118+
93119 /**
94120 * set the tinker notification id you want
95121 * @param id
@@ -98,9 +124,7 @@ public static void setTinkerNotificationId(int id) {
98124 notificationId = id ;
99125 }
100126
101- @ Override
102- protected void onHandleIntent (Intent intent ) {
103- final Context context = getApplicationContext ();
127+ private static void doApplyPatch (Context context , Intent intent ) {
104128 Tinker tinker = Tinker .with (context );
105129 tinker .getPatchReporter ().onPatchServiceStart (intent );
106130
@@ -120,7 +144,6 @@ protected void onHandleIntent(Intent intent) {
120144 long cost ;
121145 Throwable e = null ;
122146
123- increasingPriority ();
124147 PatchResult patchResult = new PatchResult ();
125148 try {
126149 if (upgradePatchProcessor == null ) {
@@ -143,57 +166,134 @@ protected void onHandleIntent(Intent intent) {
143166 patchResult .e = e ;
144167
145168 AbstractResultService .runResultService (context , patchResult , getPatchResultExtra (intent ));
146-
147169 }
148170
149- private void increasingPriority () {
171+ public static class IntentServiceRunner extends IntentService {
172+
173+ public IntentServiceRunner () {
174+ super ("TinkerPatchService" );
175+ }
176+
177+ @ Override
178+ protected void onHandleIntent (@ Nullable Intent intent ) {
179+ increasingPriority ();
180+ doApplyPatch (getApplicationContext (), intent );
181+ }
182+
183+ private void increasingPriority () {
150184// if (Build.VERSION.SDK_INT > 24) {
151185// TinkerLog.i(TAG, "for Android 7.1, we just ignore increasingPriority job");
152186// return;
153187// }
154- TinkerLog .i (TAG , "try to increase patch process priority" );
155- try {
156- Notification notification = new Notification ();
157- if (Build .VERSION .SDK_INT < 18 ) {
158- startForeground (notificationId , notification );
159- } else {
160- startForeground (notificationId , notification );
161- // start InnerService
162- startService (new Intent (this , InnerService .class ));
188+ if (Build .VERSION .SDK_INT >= 26 ) {
189+ TinkerLog .i (TAG , "for system version >= Android O, we just ignore increasingPriority "
190+ + "job to avoid crash or toasts." );
191+ return ;
163192 }
164- } catch (Throwable e ) {
165- TinkerLog .i (TAG , "try to increase patch process priority error:" + e );
166- }
167- }
168193
169- /**
170- * I don't want to do this, believe me
171- */
172- //InnerService
173- public static class InnerService extends Service {
174- @ Override
175- public void onCreate () {
176- super .onCreate ();
194+ if ("ZUK" .equals (Build .MANUFACTURER )) {
195+ TinkerLog .i (TAG , "for ZUK device, we just ignore increasingPriority "
196+ + "job to avoid crash." );
197+ return ;
198+ }
199+
200+ TinkerLog .i (TAG , "try to increase patch process priority" );
177201 try {
178- startForeground (notificationId , new Notification ());
202+ Notification notification = new Notification ();
203+ if (Build .VERSION .SDK_INT < 18 ) {
204+ startForeground (notificationId , notification );
205+ } else {
206+ startForeground (notificationId , notification );
207+ // start InnerService
208+ startService (new Intent (this , InnerService .class ));
209+ }
179210 } catch (Throwable e ) {
180- TinkerLog .e (TAG , "InnerService set service for push exception:%s." , e );
211+ TinkerLog .i (TAG , "try to increase patch process priority error:" + e );
181212 }
182- // kill
183- stopSelf ();
184213 }
185214
215+ /**
216+ * I don't want to do this, believe me
217+ */
218+ //InnerService
219+ public static class InnerService extends Service {
220+ @ Override
221+ public void onCreate () {
222+ super .onCreate ();
223+ try {
224+ startForeground (notificationId , new Notification ());
225+ } catch (Throwable e ) {
226+ TinkerLog .e (TAG , "InnerService set service for push exception:%s." , e );
227+ }
228+ // kill
229+ stopSelf ();
230+ }
231+
232+ @ Override
233+ public void onDestroy () {
234+ stopForeground (true );
235+ super .onDestroy ();
236+ }
237+
238+ @ Override
239+ public IBinder onBind (Intent intent ) {
240+ return null ;
241+ }
242+ }
243+ }
244+
245+ @ TargetApi (Build .VERSION_CODES .LOLLIPOP )
246+ public static class JobServiceRunner extends JobService {
247+ private JobAsyncTask mTask = null ;
248+
186249 @ Override
187- public void onDestroy () {
188- stopForeground (true );
189- super .onDestroy ();
250+ public boolean onStartJob (JobParameters params ) {
251+ mTask = new JobAsyncTask (this );
252+ mTask .execute (params );
253+ return true ;
190254 }
191255
192256 @ Override
193- public IBinder onBind (Intent intent ) {
194- return null ;
257+ public boolean onStopJob (JobParameters params ) {
258+ TinkerLog .w (TAG , "Stopping TinkerPatchJob service." );
259+ if (mTask != null ) {
260+ mTask .cancel (true );
261+ mTask = null ;
262+ }
263+ return false ;
195264 }
196- }
197265
266+ private static class JobAsyncTask extends AsyncTask <JobParameters , Void , Void > {
267+ private final WeakReference <JobService > mHolderRef ;
268+
269+ JobAsyncTask (JobService holder ) {
270+ mHolderRef = new WeakReference <>(holder );
271+ }
272+
273+ @ Override
274+ protected Void doInBackground (JobParameters ... paramsList ) {
275+ final JobParameters params = paramsList [0 ];
276+ final PersistableBundle extras = params .getExtras ();
277+ final Intent paramIntent = new Intent ();
278+ paramIntent .putExtra (PATCH_PATH_EXTRA , extras .getString (PATCH_PATH_EXTRA ));
279+ paramIntent .putExtra (RESULT_CLASS_EXTRA , extras .getString (RESULT_CLASS_EXTRA ));
280+ final JobService holder = mHolderRef .get ();
281+ if (holder == null ) {
282+ TinkerLog .e (TAG , "unexpected case: holder job service is null." );
283+ return null ;
284+ }
285+ doApplyPatch (holder .getApplicationContext (), paramIntent );
286+ notifyFinished (params );
287+ return null ;
288+ }
289+
290+ private void notifyFinished (JobParameters params ) {
291+ final JobService holder = mHolderRef .get ();
292+ if (holder != null ) {
293+ holder .jobFinished (params , false );
294+ }
295+ }
296+ }
297+ }
198298}
199299
0 commit comments