OSDN Git Service

No need for findViewById wrapper methods anymore
[android-x86/packages-apps-Taskbar.git] / app / src / main / java / com / farmerbb / taskbar / service / DashboardService.java
1 /* Based on code by Leonardo Fischer
2  * See https://github.com/lgfischer/WidgetHostExample
3  *
4  * Copyright 2016 Braden Farmer
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 package com.farmerbb.taskbar.service;
20
21 import android.animation.Animator;
22 import android.animation.AnimatorListenerAdapter;
23 import android.annotation.SuppressLint;
24 import android.annotation.TargetApi;
25 import android.app.Service;
26 import android.appwidget.AppWidgetHost;
27 import android.appwidget.AppWidgetHostView;
28 import android.appwidget.AppWidgetManager;
29 import android.appwidget.AppWidgetProviderInfo;
30 import android.content.BroadcastReceiver;
31 import android.content.ComponentName;
32 import android.content.Context;
33 import android.content.Intent;
34 import android.content.IntentFilter;
35 import android.content.SharedPreferences;
36 import android.content.pm.PackageManager;
37 import android.content.res.Configuration;
38 import android.graphics.Color;
39 import android.graphics.ColorMatrix;
40 import android.graphics.ColorMatrixColorFilter;
41 import android.graphics.PixelFormat;
42 import android.graphics.drawable.Drawable;
43 import android.os.Build;
44 import android.os.Bundle;
45 import android.os.Handler;
46 import android.os.IBinder;
47 import android.os.Process;
48 import android.support.v4.content.LocalBroadcastManager;
49 import android.support.v4.graphics.ColorUtils;
50 import android.util.SparseArray;
51 import android.view.MotionEvent;
52 import android.view.PointerIcon;
53 import android.view.View;
54 import android.view.ViewGroup;
55 import android.view.WindowManager;
56 import android.widget.FrameLayout;
57 import android.widget.ImageView;
58 import android.widget.LinearLayout;
59 import android.widget.TextView;
60 import android.widget.Toast;
61
62 import com.farmerbb.taskbar.R;
63 import com.farmerbb.taskbar.activity.DashboardActivity;
64 import com.farmerbb.taskbar.activity.dark.DashboardActivityDark;
65 import com.farmerbb.taskbar.util.DashboardHelper;
66 import com.farmerbb.taskbar.widget.DashboardCell;
67 import com.farmerbb.taskbar.util.FreeformHackHelper;
68 import com.farmerbb.taskbar.util.LauncherHelper;
69 import com.farmerbb.taskbar.util.U;
70
71 import java.util.List;
72
73 public class DashboardService extends Service {
74
75     private AppWidgetManager mAppWidgetManager;
76     private AppWidgetHost mAppWidgetHost;
77
78     private WindowManager windowManager;
79     private LinearLayout layout;
80
81     private SparseArray<DashboardCell> cells = new SparseArray<>();
82     private SparseArray<AppWidgetHostView> widgets = new SparseArray<>();
83
84     private final int APPWIDGET_HOST_ID = 123;
85
86     private int columns;
87     private int rows;
88     private int maxSize;
89     private int previouslySelectedCell = -1;
90
91     private View.OnClickListener ocl = view -> toggleDashboard();
92
93     private View.OnClickListener cellOcl = view -> cellClick(view, true);
94
95     private View.OnHoverListener cellOhl = (v, event) -> {
96         cellClick(v, false);
97
98         if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
99             v.setPointerIcon(PointerIcon.getSystemIcon(this, PointerIcon.TYPE_DEFAULT));
100
101         return false;
102     };
103
104     private View.OnLongClickListener olcl = v -> {
105         cellLongClick(v);
106         return true;
107     };
108
109     private View.OnGenericMotionListener ogml = (view, motionEvent) -> {
110         if(motionEvent.getAction() == MotionEvent.ACTION_BUTTON_PRESS
111                 && motionEvent.getButtonState() == MotionEvent.BUTTON_SECONDARY)
112             cellLongClick(view);
113
114         return false;
115     };
116
117     private DashboardCell.OnInterceptedLongPressListener listener = this::cellLongClick;
118
119     private BroadcastReceiver toggleReceiver = new BroadcastReceiver() {
120         @Override
121         public void onReceive(Context context, Intent intent) {
122             toggleDashboard();
123         }
124     };
125
126     private BroadcastReceiver addWidgetReceiver = new BroadcastReceiver() {
127         @Override
128         public void onReceive(Context context, Intent intent) {
129             fadeIn();
130
131             if(intent.hasExtra("appWidgetId") && intent.hasExtra("cellId")) {
132                 int appWidgetId = intent.getExtras().getInt("appWidgetId", -1);
133                 int cellId = intent.getExtras().getInt("cellId", -1);
134
135                 addWidget(appWidgetId, cellId, true);
136             }
137         }
138     };
139
140     private BroadcastReceiver removeWidgetReceiver = new BroadcastReceiver() {
141         @Override
142         public void onReceive(Context context, Intent intent) {
143             fadeIn();
144
145             if(intent.hasExtra("cellId")) {
146                 int cellId = intent.getExtras().getInt("cellId", -1);
147
148                 removeWidget(cellId, false);
149             }
150         }
151     };
152
153     private BroadcastReceiver hideReceiver = new BroadcastReceiver() {
154         @Override
155         public void onReceive(Context context, Intent intent) {
156             hideDashboard();
157         }
158     };
159
160     @Override
161     public IBinder onBind(Intent intent) {
162         return null;
163     }
164
165     @Override
166     public int onStartCommand(Intent intent, int flags, int startId) {
167         return START_STICKY;
168     }
169
170     @TargetApi(Build.VERSION_CODES.M)
171     @Override
172     public void onCreate() {
173         super.onCreate();
174
175         SharedPreferences pref = U.getSharedPreferences(this);
176         if(pref.getBoolean("dashboard", false)) {
177             if(pref.getBoolean("taskbar_active", false) || LauncherHelper.getInstance().isOnHomeScreen()) {
178                 if(U.canDrawOverlays(this))
179                     drawDashboard();
180                 else {
181                     pref.edit().putBoolean("taskbar_active", false).apply();
182
183                     stopSelf();
184                 }
185             } else stopSelf();
186         } else stopSelf();
187     }
188
189     @SuppressLint("RtlHardcoded")
190     private void drawDashboard() {
191         windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
192
193         final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
194                 WindowManager.LayoutParams.MATCH_PARENT,
195                 WindowManager.LayoutParams.MATCH_PARENT,
196                 U.getOverlayType(),
197                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
198                 PixelFormat.TRANSLUCENT);
199
200         // Initialize views
201         layout = new LinearLayout(this);
202         layout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
203         layout.setVisibility(View.GONE);
204         layout.setAlpha(0);
205
206         SharedPreferences pref = U.getSharedPreferences(this);
207         int width = pref.getInt("dashboard_width", getApplicationContext().getResources().getInteger(R.integer.dashboard_width));
208         int height = pref.getInt("dashboard_height", getApplicationContext().getResources().getInteger(R.integer.dashboard_height));
209
210         boolean isPortrait = getApplicationContext().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
211         boolean isLandscape = getApplicationContext().getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
212
213         if(isPortrait) {
214             columns = height;
215             rows = width;
216         }
217
218         if(isLandscape) {
219             columns = width;
220             rows = height;
221         }
222
223         maxSize = columns * rows;
224
225         int backgroundTint = U.getBackgroundTint(this);
226         int accentColor = U.getAccentColor(this);
227         int accentColorAlt = accentColor;
228         accentColorAlt = ColorUtils.setAlphaComponent(accentColorAlt, Color.alpha(accentColorAlt) / 2);
229
230         int cellCount = 0;
231
232         for(int i = 0; i < columns; i++) {
233             LinearLayout layout2 = new LinearLayout(this);
234             layout2.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 1));
235             layout2.setOrientation(LinearLayout.VERTICAL);
236
237             for(int j = 0; j < rows; j++) {
238                 DashboardCell cellLayout = (DashboardCell) View.inflate(this, R.layout.dashboard, null);
239                 cellLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 1));
240                 cellLayout.setBackgroundColor(backgroundTint);
241                 cellLayout.setOnClickListener(cellOcl);
242                 cellLayout.setOnHoverListener(cellOhl);
243
244                 TextView empty = cellLayout.findViewById(R.id.empty);
245                 empty.setBackgroundColor(accentColorAlt);
246                 empty.setTextColor(accentColor);
247
248                 Bundle bundle = new Bundle();
249                 bundle.putInt("cellId", cellCount);
250
251                 cellLayout.setTag(bundle);
252                 cells.put(cellCount, cellLayout);
253                 cellCount++;
254
255                 layout2.addView(cellLayout);
256             }
257
258             layout.addView(layout2);
259         }
260
261         mAppWidgetManager = AppWidgetManager.getInstance(this);
262         mAppWidgetHost = new AppWidgetHost(this, APPWIDGET_HOST_ID);
263         mAppWidgetHost.startListening();
264
265         for(int i = 0; i < maxSize; i++) {
266             int appWidgetId = pref.getInt("dashboard_widget_" + Integer.toString(i), -1);
267             if(appWidgetId != -1)
268                 addWidget(appWidgetId, i, false);
269             else if(pref.getBoolean("dashboard_widget_" + Integer.toString(i) + "_placeholder", false))
270                 addPlaceholder(i);
271         }
272
273         mAppWidgetHost.stopListening();
274
275         LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
276         
277         lbm.unregisterReceiver(toggleReceiver);
278         lbm.unregisterReceiver(addWidgetReceiver);
279         lbm.unregisterReceiver(removeWidgetReceiver);
280         lbm.unregisterReceiver(hideReceiver);
281
282         lbm.registerReceiver(toggleReceiver, new IntentFilter("com.farmerbb.taskbar.TOGGLE_DASHBOARD"));
283         lbm.registerReceiver(addWidgetReceiver, new IntentFilter("com.farmerbb.taskbar.ADD_WIDGET_COMPLETED"));
284         lbm.registerReceiver(removeWidgetReceiver, new IntentFilter("com.farmerbb.taskbar.REMOVE_WIDGET_COMPLETED"));
285         lbm.registerReceiver(hideReceiver, new IntentFilter("com.farmerbb.taskbar.HIDE_DASHBOARD"));
286
287         windowManager.addView(layout, params);
288
289         new Handler().postDelayed(() -> {
290             int paddingSize = getResources().getDimensionPixelSize(R.dimen.icon_size);
291
292             switch(U.getTaskbarPosition(this)) {
293                 case "top_vertical_left":
294                 case "bottom_vertical_left":
295                     layout.setPadding(paddingSize, 0, 0, 0);
296                     break;
297                 case "top_left":
298                 case "top_right":
299                     layout.setPadding(0, paddingSize, 0, 0);
300                     break;
301                 case "top_vertical_right":
302                 case "bottom_vertical_right":
303                     layout.setPadding(0, 0, paddingSize, 0);
304                     break;
305                 case "bottom_left":
306                 case "bottom_right":
307                     layout.setPadding(0, 0, 0, paddingSize);
308                     break;
309             }
310         }, 100);
311     }
312
313     private void toggleDashboard() {
314         if(layout.getVisibility() == View.GONE)
315             showDashboard();
316         else
317             hideDashboard();
318     }
319
320     @SuppressWarnings("deprecation")
321     @TargetApi(Build.VERSION_CODES.N)
322     private void showDashboard() {
323         if(layout.getVisibility() == View.GONE) {
324             layout.setOnClickListener(ocl);
325             fadeIn();
326
327             LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent("com.farmerbb.taskbar.DASHBOARD_APPEARING"));
328             LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_START_MENU"));
329
330             boolean inFreeformMode = FreeformHackHelper.getInstance().isInFreeformWorkspace();
331
332             final SharedPreferences pref = U.getSharedPreferences(this);
333             Intent intent = null;
334
335             switch(pref.getString("theme", "light")) {
336                 case "light":
337                     intent = new Intent(this, DashboardActivity.class);
338                     break;
339                 case "dark":
340                     intent = new Intent(this, DashboardActivityDark.class);
341                     break;
342             }
343
344             if(intent != null) {
345                 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
346                 intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
347             }
348
349             if(inFreeformMode) {
350                 if(intent != null && U.hasBrokenSetLaunchBoundsApi())
351                     intent.putExtra("context_menu_fix", true);
352
353                 U.startActivityMaximized(this, intent);
354             } else
355                 startActivity(intent);
356
357             for(int i = 0; i < maxSize; i++) {
358                 final DashboardCell cellLayout = cells.get(i);
359                 final AppWidgetHostView hostView = widgets.get(i);
360
361                 if(hostView != null) {
362                     try {
363                         getPackageManager().getApplicationInfo(hostView.getAppWidgetInfo().provider.getPackageName(), 0);
364                         hostView.post(() -> {
365                             ViewGroup.LayoutParams params = hostView.getLayoutParams();
366                             params.width = cellLayout.getWidth();
367                             params.height = cellLayout.getHeight();
368                             hostView.setLayoutParams(params);
369                             hostView.updateAppWidgetSize(null, cellLayout.getWidth(), cellLayout.getHeight(), cellLayout.getWidth(), cellLayout.getHeight());
370                         });
371                     } catch (PackageManager.NameNotFoundException e) {
372                         removeWidget(i, false);
373                     } catch (NullPointerException e) {
374                         removeWidget(i, true);
375                     }
376                 }
377             }
378
379             if(!pref.getBoolean("dashboard_tutorial_shown", false)) {
380                 U.showToastLong(this, R.string.dashboard_tutorial);
381                 pref.edit().putBoolean("dashboard_tutorial_shown", true).apply();
382             }
383         }
384     }
385
386     private void hideDashboard() {
387         if(layout.getVisibility() == View.VISIBLE) {
388             layout.setOnClickListener(null);
389             fadeOut(true);
390
391             for(int i = 0; i < maxSize; i++) {
392                 FrameLayout frameLayout = cells.get(i);
393                 frameLayout.findViewById(R.id.empty).setVisibility(View.GONE);
394             }
395
396             previouslySelectedCell = -1;
397         }
398     }
399
400     private void fadeIn() {
401         mAppWidgetHost.startListening();
402
403         DashboardHelper.getInstance().setDashboardOpen(true);
404
405         layout.setVisibility(View.VISIBLE);
406         layout.animate()
407                 .alpha(1)
408                 .setDuration(getResources().getInteger(android.R.integer.config_shortAnimTime))
409                 .setListener(null);
410     }
411
412     private void fadeOut(final boolean sendIntent) {
413         mAppWidgetHost.stopListening();
414
415         DashboardHelper.getInstance().setDashboardOpen(false);
416
417         layout.animate()
418                 .alpha(0)
419                 .setDuration(getResources().getInteger(android.R.integer.config_shortAnimTime))
420                 .setListener(new AnimatorListenerAdapter() {
421                     @Override
422                     public void onAnimationEnd(Animator animation) {
423                         layout.setVisibility(View.GONE);
424                         if(sendIntent) LocalBroadcastManager.getInstance(DashboardService.this).sendBroadcast(new Intent("com.farmerbb.taskbar.DASHBOARD_DISAPPEARING"));
425                     }
426                 });
427     }
428
429     @TargetApi(Build.VERSION_CODES.M)
430     @Override
431     public void onConfigurationChanged(Configuration newConfig) {
432         super.onConfigurationChanged(newConfig);
433
434         if(layout != null) {
435             try {
436                 windowManager.removeView(layout);
437             } catch (IllegalArgumentException e) { /* Gracefully fail */ }
438
439             SharedPreferences pref = U.getSharedPreferences(this);
440             if(U.canDrawOverlays(this))
441                 drawDashboard();
442             else {
443                 pref.edit().putBoolean("taskbar_active", false).apply();
444
445                 stopSelf();
446             }
447         }
448     }
449
450     @Override
451     public void onDestroy() {
452         super.onDestroy();
453         if(layout != null)
454             try {
455                 windowManager.removeView(layout);
456             } catch (IllegalArgumentException e) { /* Gracefully fail */ }
457
458         LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
459
460         lbm.unregisterReceiver(toggleReceiver);
461         lbm.unregisterReceiver(addWidgetReceiver);
462         lbm.unregisterReceiver(removeWidgetReceiver);
463         lbm.unregisterReceiver(hideReceiver);
464
465         lbm.sendBroadcast(new Intent("com.farmerbb.taskbar.DASHBOARD_DISAPPEARING"));
466     }
467
468     private void cellClick(View view, boolean isActualClick) {
469         Bundle bundle = (Bundle) view.getTag();
470         int cellId = bundle.getInt("cellId");
471         int appWidgetId = bundle.getInt("appWidgetId", -1);
472
473         int currentlySelectedCell = appWidgetId == -1 ? cellId : -1;
474
475         SharedPreferences pref = U.getSharedPreferences(this);
476         boolean shouldShowPlaceholder = pref.getBoolean("dashboard_widget_" + Integer.toString(cellId) + "_placeholder", false);
477         if(isActualClick && ((appWidgetId == -1 && currentlySelectedCell == previouslySelectedCell) || shouldShowPlaceholder)) {
478             fadeOut(false);
479
480             FrameLayout frameLayout = cells.get(currentlySelectedCell);
481             frameLayout.findViewById(R.id.empty).setVisibility(View.GONE);
482
483             Intent intent = new Intent("com.farmerbb.taskbar.ADD_WIDGET_REQUESTED");
484             intent.putExtra("appWidgetId", APPWIDGET_HOST_ID);
485             intent.putExtra("cellId", cellId);
486             LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
487
488             if(shouldShowPlaceholder) {
489                 String providerName = pref.getString("dashboard_widget_" + Integer.toString(cellId) + "_provider", "null");
490                 if(!providerName.equals("null")) {
491                     ComponentName componentName = ComponentName.unflattenFromString(providerName);
492
493                     List<AppWidgetProviderInfo> providerInfoList = mAppWidgetManager.getInstalledProvidersForProfile(Process.myUserHandle());
494                     for(AppWidgetProviderInfo info : providerInfoList) {
495                         if(info.provider.equals(componentName)) {
496                             U.showToast(this, getString(R.string.widget_restore_toast, info.loadLabel(getPackageManager())), Toast.LENGTH_SHORT);
497                             break;
498                         }
499                     }
500                 }
501             }
502
503             previouslySelectedCell = -1;
504         } else {
505             for(int i = 0; i < maxSize; i++) {
506                 FrameLayout frameLayout = cells.get(i);
507                 frameLayout.findViewById(R.id.empty).setVisibility(i == currentlySelectedCell && !shouldShowPlaceholder ? View.VISIBLE : View.GONE);
508             }
509
510             previouslySelectedCell = currentlySelectedCell;
511         }
512     }
513
514     private void cellLongClick(View view) {
515         fadeOut(false);
516
517         Bundle bundle = (Bundle) view.getTag();
518         int cellId = bundle.getInt("cellId");
519
520         Intent intent = new Intent("com.farmerbb.taskbar.REMOVE_WIDGET_REQUESTED");
521         intent.putExtra("cellId", cellId);
522         LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
523     }
524
525     private void addWidget(int appWidgetId, int cellId, boolean shouldSave) {
526         AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
527
528         final DashboardCell cellLayout = cells.get(cellId);
529         final AppWidgetHostView hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
530         hostView.setAppWidget(appWidgetId, appWidgetInfo);
531
532         Bundle bundle = new Bundle();
533         bundle.putInt("cellId", cellId);
534         hostView.setTag(bundle);
535
536         cellLayout.findViewById(R.id.empty).setVisibility(View.GONE);
537         cellLayout.findViewById(R.id.placeholder).setVisibility(View.GONE);
538         cellLayout.setOnLongClickListener(olcl);
539         cellLayout.setOnGenericMotionListener(ogml);
540         cellLayout.setOnInterceptedLongPressListener(listener);
541
542         LinearLayout linearLayout = cellLayout.findViewById(R.id.dashboard);
543         linearLayout.addView(hostView);
544
545         Bundle bundle2 = (Bundle) cellLayout.getTag();
546         bundle2.putInt("appWidgetId", appWidgetId);
547         cellLayout.setTag(bundle2);
548
549         widgets.put(cellId, hostView);
550
551         if(shouldSave) {
552             SharedPreferences pref = U.getSharedPreferences(this);
553             SharedPreferences.Editor editor = pref.edit();
554             editor.putInt("dashboard_widget_" + Integer.toString(cellId), appWidgetId);
555             editor.putString("dashboard_widget_" + Integer.toString(cellId) + "_provider", appWidgetInfo.provider.flattenToString());
556             editor.remove("dashboard_widget_" + Integer.toString(cellId) + "_placeholder");
557             editor.apply();
558         }
559
560         new Handler().post(() -> {
561             ViewGroup.LayoutParams params = hostView.getLayoutParams();
562             params.width = cellLayout.getWidth();
563             params.height = cellLayout.getHeight();
564             hostView.setLayoutParams(params);
565             hostView.updateAppWidgetSize(null, cellLayout.getWidth(), cellLayout.getHeight(), cellLayout.getWidth(), cellLayout.getHeight());
566         });
567     }
568
569     private void removeWidget(int cellId, boolean tempRemove) {
570         widgets.remove(cellId);
571
572         DashboardCell cellLayout = cells.get(cellId);
573         Bundle bundle = (Bundle) cellLayout.getTag();
574
575         mAppWidgetHost.deleteAppWidgetId(bundle.getInt("appWidgetId"));
576         bundle.remove("appWidgetId");
577
578         LinearLayout linearLayout = cellLayout.findViewById(R.id.dashboard);
579         linearLayout.removeAllViews();
580
581         cellLayout.setTag(bundle);
582         cellLayout.setOnClickListener(cellOcl);
583         cellLayout.setOnHoverListener(cellOhl);
584         cellLayout.setOnLongClickListener(null);
585         cellLayout.setOnGenericMotionListener(null);
586         cellLayout.setOnInterceptedLongPressListener(null);
587
588         SharedPreferences pref = U.getSharedPreferences(this);
589         SharedPreferences.Editor editor = pref.edit();
590         editor.remove("dashboard_widget_" + Integer.toString(cellId));
591
592         if(tempRemove) {
593             editor.putBoolean("dashboard_widget_" + Integer.toString(cellId) + "_placeholder", true);
594             addPlaceholder(cellId);
595         } else
596             editor.remove("dashboard_widget_" + Integer.toString(cellId) + "_provider");
597
598         editor.apply();
599     }
600
601     private void addPlaceholder(int cellId) {
602         FrameLayout placeholder = cells.get(cellId).findViewById(R.id.placeholder);
603         SharedPreferences pref = U.getSharedPreferences(this);
604         String providerName = pref.getString("dashboard_widget_" + Integer.toString(cellId) + "_provider", "null");
605
606         if(!providerName.equals("null")) {
607             ImageView imageView = placeholder.findViewById(R.id.placeholder_image);
608             ComponentName componentName = ComponentName.unflattenFromString(providerName);
609
610             List<AppWidgetProviderInfo> providerInfoList = mAppWidgetManager.getInstalledProvidersForProfile(Process.myUserHandle());
611             for(AppWidgetProviderInfo info : providerInfoList) {
612                 if(info.provider.equals(componentName)) {
613                     Drawable drawable = info.loadPreviewImage(this, -1);
614                     if(drawable == null) drawable = info.loadIcon(this, -1);
615
616                     ColorMatrix matrix = new ColorMatrix();
617                     matrix.setSaturation(0);
618
619                     imageView.setImageDrawable(drawable);
620                     imageView.setColorFilter(new ColorMatrixColorFilter(matrix));
621                     break;
622                 }
623             }
624         }
625
626         placeholder.setVisibility(View.VISIBLE);
627     }
628 }