/*
* Tencent is pleased to support the open source community by making
* Tencent GT (Version 2.4 and subsequent versions) available.
*
* Notwithstanding anything to the contrary herein, any previous version
* of Tencent GT shall not be subject to the license hereunder.
* All right, title, and interest, including all intellectual property rights,
* in and to the previous version of Tencent GT (including any and all copies thereof)
* shall be owned and retained by Tencent and subject to the license under the
* Tencent GT End User License Agreement (http://gt.qq.com/wp-content/EULA_EN.html).
*
* Copyright (C) 2015 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the MIT License (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://opensource.org/licenses/MIT
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.wstt.gt.service;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.widget.ImageView;
import com.tencent.wstt.gt.GTApp;
import com.tencent.wstt.gt.R;
import com.tencent.wstt.gt.activity.GTMainActivity;
import com.tencent.wstt.gt.activity.SplashActivity;
import com.tencent.wstt.gt.api.utils.DeviceUtils;
public class GTLogo extends Service {
WindowManager wm = null;
WindowManager.LayoutParams wmParams = null;
public static View entrance_view;
private float mTouchStartX;
private float mTouchStartY;
private float x;
private float y;
public static ImageView entrance_img;
private float moveX;
private float moveY;
private float ProX;
private float ProY;
private float move_oldX = -1000;
private float move_oldY = -1000;
// 处理logo的短按、长按事件用
private boolean keyUpDown = false;
private int timer = 0;
private boolean move_event = false;
// logo靠边的动画处理
private int logo_width = 0;
private int dev_width = 0;
private int half_logo_width = 0;
private int cur_X = 0;
private int mAnimDistance = 20;
private final int MSG_ANIMATION_ToLeft = 1;
private final int MSG_ANIMATION_ToRight = 2;
private final int MSG_ANIMATION_FINISH = 3;
// 从悬浮窗切到logo后logo的重定位处理
private static int redirect_x = -5000; // 这里设这个初始值,是因为屏幕上不可能取道这个值
private static int redirect_y = -5000;
public static boolean refresh_logo_flag = false;
public static boolean fromFloatview_pos = false;
public static boolean gtLogoRunned = false;
public static boolean gtlogo_run_flag = true;
private final int ID_FLOATVIEW = 1;
public void onCreate() {
super.onCreate();
gtLogoRunned = true;
entrance_view = LayoutInflater.from(this).inflate(R.layout.gt_entrance,
null);
entrance_img = (ImageView) entrance_view
.findViewById(R.id.entrance_img);
Drawable drawable = getResources().getDrawable(R.drawable.logo3);
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
Bitmap bitmap = bitmapDrawable.getBitmap();
entrance_img.setImageBitmap(bitmap);
entrance_img.setBackgroundColor(0);
entrance_img.setVisibility(View.VISIBLE);
createView();
// 新启一个线程处理数据,如果有UI变化,通过线程去让handler更新UI
refresh_logo_flag = true;
Thread thread = new Thread(new MyRunnable());
thread.start();
}
public class MyRunnable implements Runnable {
public void run() {
while (refresh_logo_flag) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Message msg = logo_handler.obtainMessage();
msg.what = 0;
msg.sendToTarget();
if (GTServiceController.INSTANCE
.getServiceControllerSwitchState()
&& ID_FLOATVIEW == GTServiceController.INSTANCE
.getCurAviableService()) {
Message myMsg = logo_handler.obtainMessage();
myMsg.what = 1;
myMsg.sendToTarget();
GTServiceController.INSTANCE
.setServiceControllerSwitchStateClose();
}
}
}
}
public Handler logo_handler = new Handler() {
public void handleMessage(Message msg) {
if (!checkIsInGT()) {
if (msg.what == 0) {
if (-5000 != redirect_x) {
redirectLogoPos(redirect_x, redirect_y);
redirect_x = -5000;
}
}
if (msg.what == 1) {
entrance_view.setVisibility(View.GONE);
int[] loc = new int[2];
entrance_view.getLocationOnScreen(loc);
int abs_x = loc[0];
int abs_y = loc[1];
int logo_width = entrance_view.getMeasuredWidth();
int logo_height = entrance_view.getMeasuredHeight();
int statusBar_height = DeviceUtils
.getStatusBarHeight(getApplicationContext());
int view_bottom_right_x = abs_x + logo_width;
int view_bottom_right_y = (abs_y - statusBar_height)
+ logo_height;
int view_bottom_left_x = abs_x;
int view_bottom_left_y = (abs_y - statusBar_height)
+ logo_height;
int floatview_pos_x = 0;
int floatview_pos_y = 0;
if (abs_x > dev_width / 2) { // right
floatview_pos_x = view_bottom_right_x;
floatview_pos_y = view_bottom_right_y;
} else { // left
floatview_pos_x = view_bottom_left_x;
floatview_pos_y = view_bottom_left_y;
}
GTFloatView.setReDirectXY(floatview_pos_x, floatview_pos_y);
}
checkIsVisiable();
}
super.handleMessage(msg);
}
};
private Handler clickHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
keyUpDown = true;
keyUpDownListener();
break;
case 1:
if (keyUpDown) {
keyUpDown = false;
if (timer <= 1) {
viewIsOnClick();
}
timer = 0;
}
break;
}
};
};
private int keyUpDownListener() {
new Thread() {
public void run() {
while (keyUpDown) {
try {
sleep(200);
timer++;
if (!move_event) {
if (timer >= 5) {
keyUpDown = false;
viewIsOnLongClick();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
return timer;
}
private static boolean LogoIsClick = false;
private void viewIsOnClick() {
timer = 0;
LogoIsClick = true;
if (!GTMainActivity.dlgIsShow) {
Intent intent = new Intent(GTLogo.this, SplashActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
private void viewIsOnLongClick() {
timer = 0;
GTServiceController.INSTANCE.setCurAviableService(ID_FLOATVIEW);
Message msg = logo_handler.obtainMessage();
msg.what = 1;
msg.sendToTarget();
if (!GTFloatView.floatViewRunned) {
Intent intent = new Intent(GTLogo.this, GTFloatView.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startService(intent);
}
}
private void createView() {
wm = (WindowManager) getApplicationContext().getSystemService(
Context.WINDOW_SERVICE);
wmParams = new WindowManager.LayoutParams();
wmParams.type = 2002;
wmParams.flags |= 8;
wmParams.gravity = Gravity.LEFT | Gravity.TOP;
wmParams.x = 0;
wmParams.y = 0;
wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
wmParams.format = 1;
try
{
wm.addView(entrance_view, wmParams);
}
catch (Exception e)
{
/*
* 有的Android6会报permission denied for this window type问题
* https://github.com/intercom/intercom-android/issues/116
* 在这种系统上直接屏蔽悬浮窗
*/
stopSelf();
return;
}
entrance_img.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
x = event.getRawX();
y = event.getRawY()
- DeviceUtils
.getStatusBarHeight(getApplicationContext());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
move_event = false;
mTouchStartX = event.getX();
mTouchStartY = event.getY();
ProX = event.getRawX();
ProY = event.getRawY();
clickHandler.sendEmptyMessage(0);
break;
case MotionEvent.ACTION_MOVE:
moveX = event.getRawX();
moveY = event.getRawY();
final ViewConfiguration configuration = ViewConfiguration
.get(getApplicationContext());
int mTouchSlop = configuration.getScaledTouchSlop();
// 第一次move
if (move_oldX == -1000 && move_oldY == -1000) {
move_oldX = moveX;
move_oldY = moveY;
if (Math.abs(moveX - ProX) < mTouchSlop * 2
&& Math.abs(moveY - ProY) < mTouchSlop * 2) {
move_event = false;
} else {
move_event = true;
updateViewPosition();
}
} else {
if (move_event == false) {
if (Math.abs(moveX - move_oldX) < mTouchSlop * 2
&& Math.abs(moveY - move_oldY) < mTouchSlop * 2) {
move_event = false;
} else {
move_event = true;
updateViewPosition();
}
} else {
updateViewPosition();
}
}
break;
case MotionEvent.ACTION_UP:
updateViewPositionEnd();
move_oldX = -1000;
move_oldY = -1000;
mTouchStartX = mTouchStartY = 0;
clickHandler.sendEmptyMessage(1);
break;
}
return true;
}
});
}
private void updateViewPosition() {
wmParams.x = (int) (x - mTouchStartX);
wmParams.y = (int) (y - mTouchStartY);
wm.updateViewLayout(entrance_view, wmParams);
}
private void updateViewPositionEnd() {
if (LogoIsClick) {
LogoIsClick = false;
return;
}
wmParams.x = (int) (x - mTouchStartX);
wmParams.y = (int) (y - mTouchStartY);
cur_X = wmParams.x;
wm.updateViewLayout(entrance_view, wmParams);
processLogoPosition();
}
private void processLogoPosition() {
logo_width = entrance_view.getMeasuredWidth();
dev_width = DeviceUtils.getDevWidth();
half_logo_width = logo_width / 2;
if ((cur_X + half_logo_width) < dev_width / 2) {
mAnimHandler.sendEmptyMessage(MSG_ANIMATION_ToLeft);
} else {
mAnimHandler.sendEmptyMessage(MSG_ANIMATION_ToRight);
}
}
private Handler mAnimHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_ANIMATION_ToLeft:
doAnimationToLeft();
break;
case MSG_ANIMATION_ToRight:
doAnimationToRight();
break;
case MSG_ANIMATION_FINISH:
break;
}
};
};
private void doAnimationToLeft() {
if (cur_X > 0) {
cur_X -= mAnimDistance;
wmParams.x = cur_X;
wm.updateViewLayout(entrance_view, wmParams);
mAnimHandler.sendEmptyMessage(MSG_ANIMATION_ToLeft);
}
}
private void doAnimationToRight() {
if (cur_X < dev_width) {
cur_X += mAnimDistance;
wmParams.x = cur_X;
wm.updateViewLayout(entrance_view, wmParams);
mAnimHandler.sendEmptyMessage(MSG_ANIMATION_ToRight);
}
}
private boolean checkIsInGT() {
if (GTApp.isInGT()){
entrance_view.setVisibility(View.GONE);
return true;
} else {
entrance_view.setVisibility(View.VISIBLE);
return false;
}
}
void checkIsVisiable() {
int id = GTServiceController.INSTANCE.getCurAviableService();
switch (id) {
case 0:
entrance_view.setVisibility(View.VISIBLE);
if (GTServiceController.INSTANCE.show_alert) {
Drawable drawable = getResources()
.getDrawable(R.drawable.logo1);
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
Bitmap bitmap = bitmapDrawable.getBitmap();
entrance_img.setImageBitmap(bitmap);
entrance_img.setBackgroundColor(0);
entrance_img.setVisibility(View.VISIBLE);
} else {
Drawable drawable = getResources().getDrawable(
R.drawable.gt_entrlogo);
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
Bitmap bitmap = bitmapDrawable.getBitmap();
entrance_img.setImageBitmap(bitmap);
entrance_img.setBackgroundColor(0);
entrance_img.setVisibility(View.VISIBLE);
}
break;
case 1:
entrance_view.setVisibility(View.GONE);
break;
}
}
public static void setReDirectXY(int x, int y) {
redirect_x = x;
redirect_y = y;
}
private void redirectLogoPos(int x, int y) {
wmParams.x = x;
wmParams.y = y;
cur_X = wmParams.x;
wm.updateViewLayout(entrance_view, wmParams);
entrance_view.setVisibility(View.VISIBLE);
processLogoPosition();
}
@Override
public void onDestroy() {
refresh_logo_flag = false;
try
{
/*
* 有的Android6会报permission denied for this window type问题
* https://github.com/intercom/intercom-android/issues/116
* 在这种系统上直接屏蔽悬浮窗
*/
wm.removeView(entrance_view);
}
catch (Exception e)
{
}
super.onDestroy();
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
}