OSDN Git Service

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