1 // Copyright (c) 2014 Intel Corporation. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.xwalk.core;
7 import java.lang.Runnable;
9 import android.app.Activity;
10 import android.app.Dialog;
11 import android.content.BroadcastReceiver;
12 import android.content.Context;
13 import android.content.DialogInterface;
14 import android.content.Intent;
15 import android.content.IntentFilter;
16 import android.graphics.Bitmap;
17 import android.graphics.BitmapFactory;
18 import android.graphics.drawable.BitmapDrawable;
19 import android.graphics.drawable.Drawable;
20 import android.graphics.Rect;
21 import android.os.Bundle;
22 import android.util.Log;
23 import android.view.Gravity;
24 import android.view.KeyEvent;
25 import android.view.View;
26 import android.view.ViewGroup;
27 import android.view.Window;
28 import android.view.WindowManager;
29 import android.widget.FrameLayout;
30 import android.widget.LinearLayout;
32 import org.chromium.content.browser.ContentViewRenderView.FirstRenderedFrameListener;
34 // Provisionally set it as public due to the use of launch screen extension.
35 // TODO(yongsheng): remove public modifier.
36 public class XWalkLaunchScreenManager
37 implements FirstRenderedFrameListener, DialogInterface.OnShowListener, PageLoadListener {
38 // This string will be initialized before extension initialized,
39 // and used by LaunchScreenExtension.
40 private static String mIntentFilterStr;
42 private XWalkView mXWalkView;
43 private Activity mActivity;
44 private Context mLibContext;
45 private Dialog mLaunchScreenDialog;
46 private boolean mPageLoadFinished;
47 private ReadyWhenType mReadyWhen;
48 private boolean mFirstFrameReceived;
49 private BroadcastReceiver mLaunchScreenReadyWhenReceiver;
50 private boolean mCustomHideLaunchScreen;
52 private enum ReadyWhenType {
59 public XWalkLaunchScreenManager(Context context, XWalkView xwView) {
61 mLibContext = context;
62 mActivity = mXWalkView.getActivity();
63 mIntentFilterStr = mActivity.getPackageName() + ".hideLaunchScreen";
66 public void displayLaunchScreen(String readyWhen) {
67 if (mXWalkView == null) return;
68 setReadyWhen(readyWhen);
70 Runnable runnable = new Runnable() {
72 int resId = mActivity.getResources().getIdentifier(
73 "launchscreen", "drawable", mActivity.getPackageName());
74 if (resId == 0) return;
76 // Can not use the drawable directly in shared mode, need to decode it and create a new drawable.
77 Bitmap bitmap = BitmapFactory.decodeResource(mActivity.getResources(), resId);
78 Drawable finalDrawable = new BitmapDrawable(mActivity.getResources(), bitmap);
80 mLaunchScreenDialog = new Dialog(mLibContext, android.R.style.Theme_Holo_Light_NoActionBar);
81 if ((mActivity.getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0) {
82 mLaunchScreenDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
83 WindowManager.LayoutParams.FLAG_FULLSCREEN);
85 mLaunchScreenDialog.getWindow().setBackgroundDrawable(finalDrawable);
86 mLaunchScreenDialog.setOnKeyListener(new Dialog.OnKeyListener() {
88 public boolean onKey(DialogInterface arg0, int keyCode,
90 if (keyCode == KeyEvent.KEYCODE_BACK) {
91 mLaunchScreenDialog.dismiss();
92 mActivity.onBackPressed();
97 mLaunchScreenDialog.setOnShowListener(XWalkLaunchScreenManager.this);
98 mLaunchScreenDialog.show();
99 if (mReadyWhen == ReadyWhenType.CUSTOM) registerBroadcastReceiver();
102 mActivity.runOnUiThread(runnable);
106 public void onFirstFrameReceived() {
107 mFirstFrameReceived = true;
108 hideLaunchScreenWhenReady();
112 public void onShow(DialogInterface dialog) {
113 mActivity.getWindow().setBackgroundDrawable(null);
114 if (mFirstFrameReceived) hideLaunchScreenWhenReady();
118 public void onPageFinished(String url) {
119 mPageLoadFinished = true;
120 hideLaunchScreenWhenReady();
123 public static String getHideLaunchScreenFilterStr() {
124 return mIntentFilterStr;
127 private void registerBroadcastReceiver() {
128 IntentFilter intentFilter = new IntentFilter(mIntentFilterStr);
129 mLaunchScreenReadyWhenReceiver = new BroadcastReceiver() {
131 public void onReceive(Context context, Intent intent) {
132 mCustomHideLaunchScreen = true;
133 hideLaunchScreenWhenReady();
136 mActivity.registerReceiver(mLaunchScreenReadyWhenReceiver, intentFilter);
139 private void hideLaunchScreenWhenReady() {
140 if (mLaunchScreenDialog == null || !mFirstFrameReceived) return;
141 if (mReadyWhen == ReadyWhenType.FIRST_PAINT) {
142 performHideLaunchScreen();
143 } else if (mReadyWhen == ReadyWhenType.USER_INTERACTIVE) {
144 // TODO: Need to listen js DOMContentLoaded event,
145 // will be implemented in the next step.
146 performHideLaunchScreen();
147 } else if (mReadyWhen == ReadyWhenType.COMPLETE) {
148 if (mPageLoadFinished) performHideLaunchScreen();
149 } else if (mReadyWhen == ReadyWhenType.CUSTOM) {
150 if (mCustomHideLaunchScreen) performHideLaunchScreen();
154 private void performHideLaunchScreen() {
155 mLaunchScreenDialog.dismiss();
156 mLaunchScreenDialog = null;
157 if (mReadyWhen == ReadyWhenType.CUSTOM) {
158 mActivity.unregisterReceiver(mLaunchScreenReadyWhenReceiver);
162 private void setReadyWhen(String readyWhen) {
163 if (readyWhen.equals("first-paint")) {
164 mReadyWhen = ReadyWhenType.FIRST_PAINT;
165 } else if (readyWhen.equals("user-interactive")) {
166 mReadyWhen = ReadyWhenType.USER_INTERACTIVE;
167 } else if (readyWhen.equals("complete")) {
168 mReadyWhen = ReadyWhenType.COMPLETE;
169 } else if (readyWhen.equals("custom")) {
170 mReadyWhen = ReadyWhenType.CUSTOM;
172 mReadyWhen = ReadyWhenType.FIRST_PAINT;