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 public class XWalkLaunchScreenManager
35 implements FirstRenderedFrameListener, DialogInterface.OnShowListener, PageLoadListener {
36 // This string will be initialized before extension initialized,
37 // and used by LaunchScreenExtension.
38 private static String mIntentFilterStr;
40 private XWalkView mXWalkView;
41 private Activity mActivity;
42 private Context mLibContext;
43 private Dialog mLaunchScreenDialog;
44 private boolean mPageLoadFinished;
45 private ReadyWhenType mReadyWhen;
46 private boolean mFirstFrameReceived;
47 private BroadcastReceiver mLaunchScreenReadyWhenReceiver;
48 private boolean mCustomHideLaunchScreen;
50 private enum ReadyWhenType {
57 public XWalkLaunchScreenManager(Context context, XWalkView xwView) {
59 mLibContext = context;
60 mActivity = mXWalkView.getActivity();
61 mIntentFilterStr = mActivity.getPackageName() + ".hideLaunchScreen";
64 public void displayLaunchScreen(String readyWhen) {
65 if (mXWalkView == null) return;
66 setReadyWhen(readyWhen);
68 Runnable runnable = new Runnable() {
70 int resId = mActivity.getResources().getIdentifier(
71 "launchscreen", "drawable", mActivity.getPackageName());
72 if (resId == 0) return;
74 // Can not use the drawable directly in shared mode, need to decode it and create a new drawable.
75 Bitmap bitmap = BitmapFactory.decodeResource(mActivity.getResources(), resId);
76 Drawable finalDrawable = new BitmapDrawable(mActivity.getResources(), bitmap);
78 mLaunchScreenDialog = new Dialog(mLibContext, android.R.style.Theme_Holo_Light_NoActionBar);
79 if ((mActivity.getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0) {
80 mLaunchScreenDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
81 WindowManager.LayoutParams.FLAG_FULLSCREEN);
83 mLaunchScreenDialog.getWindow().setBackgroundDrawable(finalDrawable);
84 mLaunchScreenDialog.setOnKeyListener(new Dialog.OnKeyListener() {
86 public boolean onKey(DialogInterface arg0, int keyCode,
88 if (keyCode == KeyEvent.KEYCODE_BACK) {
89 mLaunchScreenDialog.dismiss();
90 mActivity.onBackPressed();
95 mLaunchScreenDialog.setOnShowListener(XWalkLaunchScreenManager.this);
96 mLaunchScreenDialog.show();
97 if (mReadyWhen == ReadyWhenType.CUSTOM) registerBroadcastReceiver();
100 mActivity.runOnUiThread(runnable);
104 public void onFirstFrameReceived() {
105 mFirstFrameReceived = true;
106 hideLaunchScreenWhenReady();
110 public void onShow(DialogInterface dialog) {
111 mActivity.getWindow().setBackgroundDrawable(null);
112 if (mFirstFrameReceived) hideLaunchScreenWhenReady();
116 public void onPageFinished(String url) {
117 mPageLoadFinished = true;
118 hideLaunchScreenWhenReady();
121 public static String getHideLaunchScreenFilterStr() {
122 return mIntentFilterStr;
125 private void registerBroadcastReceiver() {
126 IntentFilter intentFilter = new IntentFilter(mIntentFilterStr);
127 mLaunchScreenReadyWhenReceiver = new BroadcastReceiver() {
129 public void onReceive(Context context, Intent intent) {
130 mCustomHideLaunchScreen = true;
131 hideLaunchScreenWhenReady();
134 mActivity.registerReceiver(mLaunchScreenReadyWhenReceiver, intentFilter);
137 private void hideLaunchScreenWhenReady() {
138 if (mLaunchScreenDialog == null || !mFirstFrameReceived) return;
139 if (mReadyWhen == ReadyWhenType.FIRST_PAINT) {
140 performHideLaunchScreen();
141 } else if (mReadyWhen == ReadyWhenType.USER_INTERACTIVE) {
142 // TODO: Need to listen js DOMContentLoaded event,
143 // will be implemented in the next step.
144 performHideLaunchScreen();
145 } else if (mReadyWhen == ReadyWhenType.COMPLETE) {
146 if (mPageLoadFinished) performHideLaunchScreen();
147 } else if (mReadyWhen == ReadyWhenType.CUSTOM) {
148 if (mCustomHideLaunchScreen) performHideLaunchScreen();
152 private void performHideLaunchScreen() {
153 mLaunchScreenDialog.dismiss();
154 mLaunchScreenDialog = null;
155 if (mReadyWhen == ReadyWhenType.CUSTOM) {
156 mActivity.unregisterReceiver(mLaunchScreenReadyWhenReceiver);
160 private void setReadyWhen(String readyWhen) {
161 if (readyWhen.equals("first-paint")) {
162 mReadyWhen = ReadyWhenType.FIRST_PAINT;
163 } else if (readyWhen.equals("user-interactive")) {
164 mReadyWhen = ReadyWhenType.USER_INTERACTIVE;
165 } else if (readyWhen.equals("complete")) {
166 mReadyWhen = ReadyWhenType.COMPLETE;
167 } else if (readyWhen.equals("custom")) {
168 mReadyWhen = ReadyWhenType.CUSTOM;
170 mReadyWhen = ReadyWhenType.FIRST_PAINT;