blob: 961c7ddfc7227bacb6c7c52c44864c14f5b4f77d [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.mojo.android;
import android.app.Application.ActivityLifecycleCallbacks;
import android.content.ActivityNotFoundException;
import android.content.pm.ActivityInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.SoundEffectConstants;
import android.view.View;
import org.chromium.mojo.bindings.InterfaceRequest;
import org.chromium.mojo.system.MojoException;
import org.chromium.mojom.activity.Activity;
import org.chromium.mojom.activity.AuralFeedbackType;
import org.chromium.mojom.activity.ComponentName;
import org.chromium.mojom.activity.HapticFeedbackType;
import org.chromium.mojom.activity.Intent;
import org.chromium.mojom.activity.ScreenOrientation;
import org.chromium.mojom.activity.StringExtra;
import org.chromium.mojom.activity.SystemUiVisibility;
import org.chromium.mojom.activity.TaskDescription;
import org.chromium.mojom.activity.UserFeedback;
/**
* Android implementation of Activity.
*
* This is a port of
* https://github.com/flutter/engine/blob/master/sky/services/activity/src/org/domokit/activity/ActivityImpl.java
*/
public class ActivityImpl implements Activity {
private static final String TAG = "AndroidImpl";
private final android.app.Activity mActivity;
private int mVisibility = SystemUiVisibility.STANDARD;
private static class UserFeedBackImpl implements UserFeedback {
private final View mView;
public UserFeedBackImpl(View view) {
mView = view;
}
@Override
public void close() {}
@Override
public void onConnectionError(MojoException e) {}
/**
* @see UserFeedback#performHapticFeedback(int)
*/
@Override
public void performHapticFeedback(int type) {
int androidType = 0;
switch (type) {
case HapticFeedbackType.LONG_PRESS:
androidType = HapticFeedbackConstants.LONG_PRESS;
break;
case HapticFeedbackType.VIRTUAL_KEY:
androidType = HapticFeedbackConstants.VIRTUAL_KEY;
break;
case HapticFeedbackType.KEYBOARD_TAP:
androidType = HapticFeedbackConstants.KEYBOARD_TAP;
break;
case HapticFeedbackType.CLOCK_TICK:
androidType = HapticFeedbackConstants.CLOCK_TICK;
break;
default:
Log.e(TAG, "Unknown HapticFeedbackType " + type);
return;
}
mView.performHapticFeedback(
androidType, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
/**
* @see UserFeedback#performAuralFeedback(int)
*/
@Override
public void performAuralFeedback(int type) {
int androidType = 0;
switch (type) {
case AuralFeedbackType.CLICK:
androidType = SoundEffectConstants.CLICK;
break;
case AuralFeedbackType.NAVIGATION_LEFT:
androidType = SoundEffectConstants.NAVIGATION_LEFT;
break;
case AuralFeedbackType.NAVIGATION_UP:
androidType = SoundEffectConstants.NAVIGATION_UP;
break;
case AuralFeedbackType.NAVIGATION_RIGHT:
androidType = SoundEffectConstants.NAVIGATION_RIGHT;
break;
case AuralFeedbackType.NAVIGATION_DOWN:
androidType = SoundEffectConstants.NAVIGATION_DOWN;
break;
default:
Log.e(TAG, "Unknown AuralFeedbackType " + type);
return;
}
mView.playSoundEffect(androidType);
}
}
/**
* Constructor.
*/
public ActivityImpl(android.app.Activity activity) {
mActivity = activity;
activity.getApplication().registerActivityLifecycleCallbacks(
new ActivityLifecycleCallbacks() {
@Override
public void onActivityStopped(android.app.Activity activity) {}
@Override
public void onActivityStarted(android.app.Activity activity) {}
@Override
public void onActivitySaveInstanceState(
android.app.Activity activity, Bundle bundle) {}
@Override
public void onActivityResumed(android.app.Activity activity) {
if (activity == mActivity) {
updateSystemUiVisibility();
}
}
@Override
public void onActivityPaused(android.app.Activity activity) {}
@Override
public void onActivityDestroyed(android.app.Activity activity) {}
@Override
public void onActivityCreated(android.app.Activity activity, Bundle bundle) {}
});
}
@Override
public void close() {}
@Override
public void onConnectionError(MojoException e) {}
/**
* @see Activity#getUserFeedback(InterfaceRequest)
*/
@Override
public void getUserFeedback(final InterfaceRequest<UserFeedback> userFeedback) {
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
UserFeedback.MANAGER.bind(
new UserFeedBackImpl(mActivity.getWindow().getDecorView()), userFeedback);
}
});
}
/**
* @see Activity#startActivity(Intent)
*/
@Override
public void startActivity(Intent intent) {
final android.content.Intent androidIntent =
new android.content.Intent(intent.action, Uri.parse(intent.url));
if (intent.component != null) {
ComponentName component = intent.component;
android.content.ComponentName androidComponent =
new android.content.ComponentName(component.packageName, component.className);
androidIntent.setComponent(androidComponent);
}
if (intent.stringExtras != null) {
for (StringExtra extra : intent.stringExtras) {
androidIntent.putExtra(extra.name, extra.value);
}
}
if (intent.flags != 0) {
androidIntent.setFlags(intent.flags);
}
if (intent.type != null) {
androidIntent.setType(intent.type);
}
try {
mActivity.startActivity(androidIntent);
} catch (ActivityNotFoundException e) {
Log.e(TAG, "Unable to startActivity", e);
}
}
/**
* @see Activity#finishCurrentActivity()
*/
@Override
public void finishCurrentActivity() {
Log.e(TAG, "finishCurrentActivity() is not implemented.");
}
/**
* @see Activity#setTaskDescription(TaskDescription)
*/
@Override
public void setTaskDescription(TaskDescription description) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return;
}
mActivity.setTaskDescription(new android.app.ActivityManager.TaskDescription(
description.label, null, description.primaryColor));
}
/**
* @see Activity#setSystemUiVisibility(int)
*/
@Override
public void setSystemUiVisibility(int visibility) {
mVisibility = visibility;
updateSystemUiVisibility();
}
/**
* @see Activity#setRequestedOrientation(int)
*/
@Override
public void setRequestedOrientation(int orientation) {
int androidOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
switch (orientation) {
case ScreenOrientation.UNSPECIFIED:
androidOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
break;
case ScreenOrientation.LANDSCAPE:
androidOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
break;
case ScreenOrientation.PORTRAIT:
androidOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
break;
case ScreenOrientation.NOSENSOR:
androidOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
break;
default:
Log.w(TAG,
"Unable to set the requested orientation. Unknown value: " + orientation);
break;
}
mActivity.setRequestedOrientation(androidOrientation);
}
private void updateSystemUiVisibility() {
int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
if (mVisibility >= SystemUiVisibility.FULLSCREEN) {
flags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
}
if (mVisibility >= SystemUiVisibility.IMMERSIVE) {
flags |= View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
}
final int finalFlags = flags;
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mActivity.getWindow().getDecorView().setSystemUiVisibility(finalFlags);
}
});
}
}