Commit 7e27ec13 by 宁斌

1、打印流程可視化調整 2、prj長連接替換輪詢

parent d315d8ac
...@@ -40,7 +40,7 @@ import com.gingersoft.gsa.cloud.common.constans.DeliveryPickConstans; ...@@ -40,7 +40,7 @@ import com.gingersoft.gsa.cloud.common.constans.DeliveryPickConstans;
import com.gingersoft.gsa.cloud.common.constans.ExpandConstant; import com.gingersoft.gsa.cloud.common.constans.ExpandConstant;
import com.gingersoft.gsa.cloud.common.core.restaurant.RestaurantInfoManager; import com.gingersoft.gsa.cloud.common.core.restaurant.RestaurantInfoManager;
import com.gingersoft.gsa.cloud.common.core.restaurant.utils.RestaurantExpandInfoUtils; import com.gingersoft.gsa.cloud.common.core.restaurant.utils.RestaurantExpandInfoUtils;
import com.gingersoft.gsa.cloud.common.service.GetInfoUpdateService; import com.gingersoft.gsa.cloud.common.service.DataNotificationService;
import com.gingersoft.gsa.cloud.common.utils.other.TextUtil; import com.gingersoft.gsa.cloud.common.utils.other.TextUtil;
import com.gingersoft.gsa.cloud.common.utils.toast.ToastUtils; import com.gingersoft.gsa.cloud.common.utils.toast.ToastUtils;
import com.gingersoft.gsa.cloud.ui.utils.AppDialog; import com.gingersoft.gsa.cloud.ui.utils.AppDialog;
...@@ -220,7 +220,7 @@ public class ColdChainMainActivity extends BaseFragmentActivity<ColdChainMainPre ...@@ -220,7 +220,7 @@ public class ColdChainMainActivity extends BaseFragmentActivity<ColdChainMainPre
private void initService() { private void initService() {
//開啟websocket //開啟websocket
Intent intent = new Intent(getApplicationContext(), GetInfoUpdateService.class); Intent intent = new Intent(getApplicationContext(), DataNotificationService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent); startForegroundService(intent);
} else { } else {
...@@ -235,13 +235,13 @@ public class ColdChainMainActivity extends BaseFragmentActivity<ColdChainMainPre ...@@ -235,13 +235,13 @@ public class ColdChainMainActivity extends BaseFragmentActivity<ColdChainMainPre
registerReceiver(clearHeartBroadcastReceiver, intentFilter); registerReceiver(clearHeartBroadcastReceiver, intentFilter);
} }
private GetInfoUpdateService.MyBind bind = null; private DataNotificationService.MyBind bind = null;
private ServiceConnection serviceConnection = new ServiceConnection() { private ServiceConnection serviceConnection = new ServiceConnection() {
@Override @Override
public void onServiceConnected(ComponentName name, IBinder service) { public void onServiceConnected(ComponentName name, IBinder service) {
bind = (GetInfoUpdateService.MyBind) service; bind = (DataNotificationService.MyBind) service;
if (bind != null) { if (bind != null) {
bind.setOnPostCallBack(type -> { bind.setOnPostCallBack(type -> {
// -1斷開連接,\n-2:消息傳輸錯誤,\n0:連接消息,\n1:登錄通知,\n2:登出通知,\n3:外賣送單通知,\n4:自取送單通知,\n5:歷史訂單通知,\n6:修改訂單狀態通知,\n7:支付成功通知" // -1斷開連接,\n-2:消息傳輸錯誤,\n0:連接消息,\n1:登錄通知,\n2:登出通知,\n3:外賣送單通知,\n4:自取送單通知,\n5:歷史訂單通知,\n6:修改訂單狀態通知,\n7:支付成功通知"
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
</intent-filter> </intent-filter>
</activity> </activity>
<service android:name="com.gingersoft.gsa.cloud.common.service.GetInfoUpdateService" /> <service android:name="com.gingersoft.gsa.cloud.common.service.DataNotificationService" />
<meta-data <meta-data
android:name="com.gingersoft.gsa.cloud.common.config.globalconfig.GlobalConfiguration" android:name="com.gingersoft.gsa.cloud.common.config.globalconfig.GlobalConfiguration"
......
...@@ -7,7 +7,7 @@ import com.billy.cc.core.component.CCResult; ...@@ -7,7 +7,7 @@ import com.billy.cc.core.component.CCResult;
import com.billy.cc.core.component.CCUtil; import com.billy.cc.core.component.CCUtil;
import com.billy.cc.core.component.IComponent; import com.billy.cc.core.component.IComponent;
import com.gingersoft.gsa.cloud.component.ComponentName; import com.gingersoft.gsa.cloud.component.ComponentName;
import com.gingersoft.gsa.cloud.common.service.GetInfoUpdateService; import com.gingersoft.gsa.cloud.common.service.DataNotificationService;
import com.gingersoft.gsa.delivery_pick_mode.data.network.ServiceCreator; import com.gingersoft.gsa.delivery_pick_mode.data.network.ServiceCreator;
import com.gingersoft.gsa.delivery_pick_mode.mvp.ui.activity.PrjQueryActivity; import com.gingersoft.gsa.delivery_pick_mode.mvp.ui.activity.PrjQueryActivity;
import com.gingersoft.gsa.delivery_pick_mode.mvp.ui.activity.SendOrderActivity; import com.gingersoft.gsa.delivery_pick_mode.mvp.ui.activity.SendOrderActivity;
...@@ -52,7 +52,7 @@ public class DeliveryPickComponent implements IComponent { ...@@ -52,7 +52,7 @@ public class DeliveryPickComponent implements IComponent {
CC.sendCCResult(cc.getCallId(), CCResult.success()); CC.sendCCResult(cc.getCallId(), CCResult.success());
break; break;
case "closeHeart": case "closeHeart":
Intent intent = new Intent(cc.getContext(), GetInfoUpdateService.class); Intent intent = new Intent(cc.getContext(), DataNotificationService.class);
cc.getContext().stopService(intent); cc.getContext().stopService(intent);
break; break;
case "historyActivity": case "historyActivity":
......
...@@ -22,7 +22,7 @@ import com.gingersoft.gsa.cloud.common.core.delivery.OrderDetails.Companion.veri ...@@ -22,7 +22,7 @@ import com.gingersoft.gsa.cloud.common.core.delivery.OrderDetails.Companion.veri
import com.gingersoft.gsa.cloud.common.core.restaurant.RestaurantInfoManager import com.gingersoft.gsa.cloud.common.core.restaurant.RestaurantInfoManager
import com.gingersoft.gsa.cloud.common.core.user.UserContext import com.gingersoft.gsa.cloud.common.core.user.UserContext
import com.gingersoft.gsa.cloud.common.logan.LoganManager import com.gingersoft.gsa.cloud.common.logan.LoganManager
import com.gingersoft.gsa.cloud.common.service.GetInfoUpdateService import com.gingersoft.gsa.cloud.common.service.DataNotificationService
import com.gingersoft.gsa.cloud.common.utils.gson.GsonUtils import com.gingersoft.gsa.cloud.common.utils.gson.GsonUtils
import com.gingersoft.gsa.cloud.common.utils.okhttpUtils.OkHttp3Utils import com.gingersoft.gsa.cloud.common.utils.okhttpUtils.OkHttp3Utils
import com.gingersoft.gsa.cloud.common.utils.other.TextUtil import com.gingersoft.gsa.cloud.common.utils.other.TextUtil
...@@ -434,8 +434,8 @@ class PageViewModel(private val repository: WeatherRepository) : ViewModel() { ...@@ -434,8 +434,8 @@ class PageViewModel(private val repository: WeatherRepository) : ViewModel() {
}, { }, {
listener.invoke(getMsgBean(0, "", false)) listener.invoke(getMsgBean(0, "", false))
it.printStackTrace() it.printStackTrace()
GetInfoUpdateService.loginfo.append("錯誤信息111:" + it.message + " LOCALIZEDMESSAGE:" + it.localizedMessage + it.cause) DataNotificationService.loginfo.append("錯誤信息111:" + it.message + " LOCALIZEDMESSAGE:" + it.localizedMessage + it.cause)
GetInfoUpdateService.loginfo.append("\n") DataNotificationService.loginfo.append("\n")
}) })
} }
...@@ -575,12 +575,12 @@ class PageViewModel(private val repository: WeatherRepository) : ViewModel() { ...@@ -575,12 +575,12 @@ class PageViewModel(private val repository: WeatherRepository) : ViewModel() {
//添加PRJ //添加PRJ
//單獨包起來,哪怕這接口報錯也不要影響到正常的邏輯 //單獨包起來,哪怕這接口報錯也不要影響到正常的邏輯
repository.addPrj(dataBean.Order_ID.toString(), restaurantId.toString(), ids.toString()) repository.addPrj(dataBean.Order_ID.toString(), restaurantId.toString(), ids.toString())
GetInfoUpdateService.loginfo.append("添加PRJ:orderId:" + dataBean.Order_ID.toString() + "restaurantId:" + restaurantId + "orderDetailsIds:" + ids.toString()) DataNotificationService.loginfo.append("添加PRJ:orderId:" + dataBean.Order_ID.toString() + "restaurantId:" + restaurantId + "orderDetailsIds:" + ids.toString())
GetInfoUpdateService.loginfo.append("\n") DataNotificationService.loginfo.append("\n")
}, { }, {
it.printStackTrace() it.printStackTrace()
GetInfoUpdateService.loginfo.append("錯誤信息222:" + it.message + " LOCALIZEDMESSAGE:" + it.localizedMessage + it.cause) DataNotificationService.loginfo.append("錯誤信息222:" + it.message + " LOCALIZEDMESSAGE:" + it.localizedMessage + it.cause)
GetInfoUpdateService.loginfo.append("\n") DataNotificationService.loginfo.append("\n")
}) })
} }
if (isPrintBill) { if (isPrintBill) {
......
...@@ -31,7 +31,7 @@ import com.gingersoft.gsa.cloud.common.constans.ExpandConstant ...@@ -31,7 +31,7 @@ import com.gingersoft.gsa.cloud.common.constans.ExpandConstant
import com.gingersoft.gsa.cloud.common.constans.FoodSummaryConstans.TAKEAWAY_TYPE import com.gingersoft.gsa.cloud.common.constans.FoodSummaryConstans.TAKEAWAY_TYPE
import com.gingersoft.gsa.cloud.common.constans.FunctionManagerConstants import com.gingersoft.gsa.cloud.common.constans.FunctionManagerConstants
import com.gingersoft.gsa.cloud.common.function.FunctionManager import com.gingersoft.gsa.cloud.common.function.FunctionManager
import com.gingersoft.gsa.cloud.common.service.GetInfoUpdateService import com.gingersoft.gsa.cloud.common.service.DataNotificationService
import com.gingersoft.gsa.cloud.common.service.PostCallBack import com.gingersoft.gsa.cloud.common.service.PostCallBack
import com.gingersoft.gsa.cloud.order.order.BaseOrder import com.gingersoft.gsa.cloud.order.order.BaseOrder
import com.gingersoft.gsa.cloud.ui.utils.AppDialog import com.gingersoft.gsa.cloud.ui.utils.AppDialog
...@@ -395,7 +395,7 @@ class DeliveryOrderMainActivity : BaseActivity<IPresenter>(), View.OnClickListen ...@@ -395,7 +395,7 @@ class DeliveryOrderMainActivity : BaseActivity<IPresenter>(), View.OnClickListen
private fun initWebsocket() { private fun initWebsocket() {
//開啟websocket //開啟websocket
val service = Intent(applicationContext, GetInfoUpdateService::class.java) val service = Intent(applicationContext, DataNotificationService::class.java)
val notification: NotificationManagerCompat = NotificationManagerCompat.from(this) val notification: NotificationManagerCompat = NotificationManagerCompat.from(this)
if (!notification.areNotificationsEnabled()) { if (!notification.areNotificationsEnabled()) {
//未開啟通知權限 //未開啟通知權限
...@@ -446,12 +446,12 @@ class DeliveryOrderMainActivity : BaseActivity<IPresenter>(), View.OnClickListen ...@@ -446,12 +446,12 @@ class DeliveryOrderMainActivity : BaseActivity<IPresenter>(), View.OnClickListen
unbindService(serviceConnection) unbindService(serviceConnection)
} }
var bind: GetInfoUpdateService.MyBind? = null var bind: DataNotificationService.MyBind? = null
var lastRefreshTime: Long = 0 var lastRefreshTime: Long = 0
private var serviceConnection = object : ServiceConnection { private var serviceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName, service: IBinder) { override fun onServiceConnected(name: ComponentName, service: IBinder) {
bind = service as GetInfoUpdateService.MyBind bind = service as DataNotificationService.MyBind
bind?.let { it -> bind?.let { it ->
it.setOnPostCallBack(object : PostCallBack { it.setOnPostCallBack(object : PostCallBack {
override fun callBack(type: Int) { override fun callBack(type: Int) {
......
...@@ -5,7 +5,7 @@ import android.widget.TextView; ...@@ -5,7 +5,7 @@ import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import com.gingersoft.gsa.cloud.common.service.GetInfoUpdateService; import com.gingersoft.gsa.cloud.common.service.DataNotificationService;
import com.gingersoft.gsa.delivery_pick_mode.R; import com.gingersoft.gsa.delivery_pick_mode.R;
public class LogActivity extends AppCompatActivity { public class LogActivity extends AppCompatActivity {
...@@ -16,13 +16,13 @@ public class LogActivity extends AppCompatActivity { ...@@ -16,13 +16,13 @@ public class LogActivity extends AppCompatActivity {
setContentView(R.layout.activity_log); setContentView(R.layout.activity_log);
loadInfo(); loadInfo();
findViewById(R.id.btn_clear_log).setOnClickListener(v -> { findViewById(R.id.btn_clear_log).setOnClickListener(v -> {
GetInfoUpdateService.loginfo.setLength(0); DataNotificationService.loginfo.setLength(0);
loadInfo(); loadInfo();
}); });
findViewById(R.id.btn_back).setOnClickListener(v ->finish()); findViewById(R.id.btn_back).setOnClickListener(v ->finish());
} }
private void loadInfo() { private void loadInfo() {
((TextView) findViewById(R.id.tv_log)).setText(GetInfoUpdateService.loginfo.toString()); ((TextView) findViewById(R.id.tv_log)).setText(DataNotificationService.loginfo.toString());
} }
} }
...@@ -126,7 +126,7 @@ dependencies { ...@@ -126,7 +126,7 @@ dependencies {
addComponent 'component-delivery-pick' addComponent 'component-delivery-pick'
addComponent 'component-manager' addComponent 'component-manager'
addComponent 'component-coldchain' addComponent 'component-coldchain'
addComponent 'component-supply-chain' // addComponent 'component-supply-chain'
addComponent 'component-webview' addComponent 'component-webview'
addComponent 'component-scan' addComponent 'component-scan'
addComponent 'component-pay' addComponent 'component-pay'
......
...@@ -4,9 +4,12 @@ import android.content.ClipData; ...@@ -4,9 +4,12 @@ import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder;
import android.os.Message; import android.os.Message;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.SparseArray; import android.util.SparseArray;
...@@ -35,6 +38,7 @@ import com.gingersoft.gsa.cloud.common.function.FunctionManager; ...@@ -35,6 +38,7 @@ import com.gingersoft.gsa.cloud.common.function.FunctionManager;
import com.gingersoft.gsa.cloud.common.function.jump.ActivityJumpBean; import com.gingersoft.gsa.cloud.common.function.jump.ActivityJumpBean;
import com.gingersoft.gsa.cloud.common.function.jump.ActivityJumpStrategy; import com.gingersoft.gsa.cloud.common.function.jump.ActivityJumpStrategy;
import com.gingersoft.gsa.cloud.common.logan.LoganManager; import com.gingersoft.gsa.cloud.common.logan.LoganManager;
import com.gingersoft.gsa.cloud.common.service.DataNotificationService;
import com.gingersoft.gsa.cloud.common.utils.AppDevices; import com.gingersoft.gsa.cloud.common.utils.AppDevices;
import com.gingersoft.gsa.cloud.common.utils.JsonUtils; import com.gingersoft.gsa.cloud.common.utils.JsonUtils;
import com.gingersoft.gsa.cloud.common.utils.StytemUtils; import com.gingersoft.gsa.cloud.common.utils.StytemUtils;
...@@ -196,27 +200,15 @@ public class NewMainActivity extends BaseFragmentActivity<NewMainPresenter> impl ...@@ -196,27 +200,15 @@ public class NewMainActivity extends BaseFragmentActivity<NewMainPresenter> impl
} }
@Override @Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
}
@Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
initService();
initFuncationData(); initFuncationData();
if (((int) SPUtils.get("isFormal", 0)) != 0) { if (((int) SPUtils.get("isFormal", 0)) != 0) {
tv_version_name.setText("v_" + DeviceUtils.getVersionName(this) + "\u3000Beta"); tv_version_name.setText("v_" + DeviceUtils.getVersionName(this) + "\u3000Beta");
} else { } else {
tv_version_name.setText("v_" + DeviceUtils.getVersionName(this)); tv_version_name.setText("v_" + DeviceUtils.getVersionName(this));
} }
boolean prjServiceRunning = StytemUtils.isServiceRunning("com.joe.print.mvp.print.service.PrjService", this);
if (!prjServiceRunning) {
//開啟Prj打印服務
CC.obtainBuilder(ComponentName.COMPONENT_PRINT)
.setActionName("openPrintService")
.build()
.call();
}
} }
@Override @Override
...@@ -225,6 +217,28 @@ public class NewMainActivity extends BaseFragmentActivity<NewMainPresenter> impl ...@@ -225,6 +217,28 @@ public class NewMainActivity extends BaseFragmentActivity<NewMainPresenter> impl
updateTitleInfo(); updateTitleInfo();
} }
private void initService() {
boolean deliveryOrderServiceRunning = StytemUtils.isServiceRunning("com.gingersoft.gsa.cloud.common.service.DataNotificationService", this);
if (!deliveryOrderServiceRunning) {
Intent service = new Intent(GsaCloudApplication.getAppContext(), DataNotificationService.class);
service.putExtra(DataNotificationService.CONNECTION_TYPE, DataNotificationService.mCurrConnectionType);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(service);
} else {
startService(service);
}
}
// boolean prjServiceRunning = StytemUtils.isServiceRunning("com.joe.print.mvp.print.service.PrjService", this);
// if (!prjServiceRunning) {
// //開啟Prj打印服務
// CC.obtainBuilder(ComponentName.COMPONENT_PRINT)
// .setActionName("openPrintService")
// .build()
// .call();
// }
}
/** /**
* 初始化側邊欄菜單項 * 初始化側邊欄菜單項
*/ */
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<application <application
android:name="com.gingersoft.gsa.cloud.app.GsaCloudApplication" android:name="com.gingersoft.gsa.cloud.app.GsaCloudApplication"
android:allowBackup="true" android:allowBackup="true"
...@@ -19,8 +20,10 @@ ...@@ -19,8 +20,10 @@
android:roundIcon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme">
<activity android:name=".mvp.ui.activity.PrintAddCurrencyActivity"/> <activity android:name=".mvp.ui.activity.PrintAddCurrencyActivity" />
<activity android:name=".mvp.ui.activity.PrintActivity" /> <activity
android:name=".mvp.ui.activity.PrintActivity"
android:launchMode="singleTop" />
<activity android:name=".mvp.ui.activity.PrinterAddActivity" /> <activity android:name=".mvp.ui.activity.PrinterAddActivity" />
<activity android:name=".mvp.ui.activity.PrintTestActivity"> <activity android:name=".mvp.ui.activity.PrintTestActivity">
<intent-filter> <intent-filter>
......
...@@ -6,8 +6,10 @@ import com.billy.cc.core.component.CC; ...@@ -6,8 +6,10 @@ import com.billy.cc.core.component.CC;
import com.billy.cc.core.component.CCResult; import com.billy.cc.core.component.CCResult;
import com.billy.cc.core.component.CCUtil; import com.billy.cc.core.component.CCUtil;
import com.billy.cc.core.component.IComponent; import com.billy.cc.core.component.IComponent;
import com.gingersoft.gsa.cloud.common.constans.PrintConstans;
import com.gingersoft.gsa.cloud.component.ComponentName; import com.gingersoft.gsa.cloud.component.ComponentName;
import com.jess.arms.utils.ArmsUtils; import com.jess.arms.utils.ArmsUtils;
import com.joe.print.mvp.print.PrinterManger.PrjPtinterManager;
import com.joe.print.mvp.print.service.PrjService; import com.joe.print.mvp.print.service.PrjService;
import com.joe.print.mvp.ui.activity.PrintActivity; import com.joe.print.mvp.ui.activity.PrintActivity;
import com.joe.print.mvp.ui.activity.PrinterListActivity; import com.joe.print.mvp.ui.activity.PrinterListActivity;
...@@ -64,11 +66,14 @@ public class PrintComponent implements IComponent { ...@@ -64,11 +66,14 @@ public class PrintComponent implements IComponent {
cc.getContext().stopService(new Intent(cc.getContext(), PrjService.class)); cc.getContext().stopService(new Intent(cc.getContext(), PrjService.class));
CC.sendCCResult(cc.getCallId(), CCResult.success()); CC.sendCCResult(cc.getCallId(), CCResult.success());
break; break;
case "getPrjData":
PrjPtinterManager.getInstance(cc.getContext()).initUsbPrint();
PrjPtinterManager.getInstance(cc.getContext()).getPrjInfo();
break;
default: default:
// cc.callAsync(new IComponentCallback() { // cc.callAsync(new IComponentCallback() {
// @Override // @Override
// public void onResult(CC cc, CCResult result) { // public void onResult(CC cc, CCResult result) {
//
// } // }
// }); // });
//这个逻辑分支上没有调用CC.sendCCResult(...),是一种错误的示例 //这个逻辑分支上没有调用CC.sendCCResult(...),是一种错误的示例
......
...@@ -294,7 +294,6 @@ public class EpsonPrint implements ReceiveListener { ...@@ -294,7 +294,6 @@ public class EpsonPrint implements ReceiveListener {
Log.d("eee", "針式打印機創建數據失敗"); Log.d("eee", "針式打印機創建數據失敗");
//如果是創建數據失敗,說明這個數據有問題,移除掉 //如果是創建數據失敗,說明這個數據有問題,移除掉
bitmaps.remove(bitmap); bitmaps.remove(bitmap);
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new Exception("針式打印機添加數據失敗" + ip));
updatePrintState(PrintSocketHolder.ERROR_6); updatePrintState(PrintSocketHolder.ERROR_6);
isPrint = false; isPrint = false;
return; return;
...@@ -315,11 +314,11 @@ public class EpsonPrint implements ReceiveListener { ...@@ -315,11 +314,11 @@ public class EpsonPrint implements ReceiveListener {
if (statusInfo.getPaper() == 2) { if (statusInfo.getPaper() == 2) {
//沒紙了 //沒紙了
updatePrintState(PrintSocketHolder.ERROR_11); updatePrintState(PrintSocketHolder.ERROR_11);
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new Exception("針式打印機缺紙,打印失敗" + ip)); PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception("針式打印機缺紙,打印失敗" + ip),0);
} else { } else {
//紙張狀態異常 //紙張狀態異常
updatePrintState(PrintSocketHolder.ERROR_11); updatePrintState(PrintSocketHolder.ERROR_11);
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new Exception("針式打印機紙張異常,請重啟打印機" + ip)); PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception("針式打印機紙張異常,請重啟打印機" + ip),0);
} }
isPrint = false; isPrint = false;
return; return;
...@@ -331,7 +330,7 @@ public class EpsonPrint implements ReceiveListener { ...@@ -331,7 +330,7 @@ public class EpsonPrint implements ReceiveListener {
} catch (Exception e) { } catch (Exception e) {
Log.d("eee", "針式打印機打印失敗" + ",任務數:" + bitmaps.size() + e.getMessage()); Log.d("eee", "針式打印機打印失敗" + ",任務數:" + bitmaps.size() + e.getMessage());
updatePrintState(PrintSocketHolder.ERROR_10); updatePrintState(PrintSocketHolder.ERROR_10);
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new Exception("針式打印機打印報錯" + ip)); PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception("打印機連接成功,發送數據出現問題"),0);
mPrinter.clearCommandBuffer(); mPrinter.clearCommandBuffer();
disconnectPrinter(); disconnectPrinter();
isPrint = false; isPrint = false;
......
...@@ -26,4 +26,7 @@ public class PrinterManager { ...@@ -26,4 +26,7 @@ public class PrinterManager {
public void setDeviceBeans(List<PrinterDeviceBean> deviceBeans) { public void setDeviceBeans(List<PrinterDeviceBean> deviceBeans) {
this.deviceBeans = deviceBeans; this.deviceBeans = deviceBeans;
} }
} }
package com.joe.print.mvp.print.PrinterManger;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.IBinder;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;
import com.epson.epos2.printer.Printer;
import com.epson.epos2.printer.PrinterStatusInfo;
import com.epson.epos2.printer.ReceiveListener;
import com.gingersoft.gsa.cloud.common.constans.HttpsConstans;
import com.gingersoft.gsa.cloud.common.constans.PrintConstans;
import com.gingersoft.gsa.cloud.common.core.restaurant.RestaurantInfoManager;
import com.gingersoft.gsa.cloud.common.logan.LoganManager;
import com.gingersoft.gsa.cloud.common.printer.AidlUtil;
import com.gingersoft.gsa.cloud.common.printer.plugins.PrinterPlugins;
import com.gingersoft.gsa.cloud.common.utils.JsonUtils;
import com.gingersoft.gsa.cloud.common.utils.gson.GsonUtils;
import com.gingersoft.gsa.cloud.common.utils.okhttpUtils.OkHttp3Utils;
import com.gingersoft.gsa.cloud.common.utils.other.TextUtil;
import com.gingersoft.gsa.cloud.common.utils.threadPool.ThreadPoolManager;
import com.gingersoft.gsa.cloud.common.utils.time.TimeUtils;
import com.gingersoft.gsa.cloud.common.utils.toast.ToastUtils;
import com.gingersoft.gsa.cloud.database.bean.PrintCurrencyBean;
import com.gingersoft.gsa.cloud.database.bean.PrinterDeviceBean;
import com.gingersoft.gsa.cloud.database.utils.PrinterDeviceDaoUtils;
import com.gingersoft.gsa.cloud.print.PrintExecutor;
import com.gingersoft.gsa.cloud.print.PrinterWriter58mm;
import com.gingersoft.gsa.cloud.print.bean.PrjBean;
import com.gingersoft.gsa.cloud.print.bean.UpdateBean;
import com.hyweb.n5.lib.constant.PrinterConstant;
import com.hyweb.n5.lib.util.PrinterUtil;
import com.hyweb.n5.server.aidl.IOnPrintCallback;
import com.joe.print.mvp.print.EpsonPrint;
import com.joe.print.mvp.print.PrintPrjKitchen;
import com.joe.print.mvp.print.common.PrinterFinderCallback;
import com.joe.print.mvp.print.common.SendResultCode;
import com.joe.print.mvp.print.maker.PrjPrintMaker;
import com.joe.print.mvp.print.usb.EscCommand;
import com.joe.print.mvp.print.usb.UsbPrint;
import com.joe.print.mvp.print.usb.UsbPrinter;
import com.joe.print.mvp.print.usb.UsbPrinterFinder;
import com.joe.print.mvp.print.utils.MyPrintUtils;
import com.sunmi.peripheral.printer.InnerResultCallbcak;
import com.xuexiang.rxutil2.rxjava.RxJavaUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.io.PrintStream;
import java.net.ConnectException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileOutputStream;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import static com.gingersoft.gsa.cloud.database.bean.PrinterDeviceBean.PRINT_IP;
import static com.gingersoft.gsa.cloud.database.bean.PrinterDeviceBean.PRINT_LOCAL;
import static com.gingersoft.gsa.cloud.database.bean.PrinterDeviceBean.PRINT_PRJ_PC;
import static com.gingersoft.gsa.cloud.database.bean.PrinterDeviceBean.PRINT_USB;
/**
* Created by Wyh on 2020/1/17.
*/
public class PrjPtinterManager implements ReceiveListener {
private String TAG = "Prj";
private Context mContext;
private int totalPrj;
private int currentIndex;
private UsbPrinterFinder printerFinder;
private List<UsbPrinter> mUsbPrinters;
private volatile static PrjPtinterManager prjPtinterManager;
public static PrjPtinterManager getInstance(Context context) {
if (prjPtinterManager == null) {
synchronized (PrjPtinterManager.class) {
if (prjPtinterManager == null) {
prjPtinterManager = new PrjPtinterManager(context);
}
}
}
return prjPtinterManager;
}
public PrjPtinterManager(Context context) {
this.mContext = context;
}
public void initUsbPrint() {
if (printerFinder != null) {
return;
}
printerFinder = new UsbPrinterFinder(mContext, new PrinterFinderCallback<UsbPrinter>() {
@Override
public void onStart() {
}
@Override
public void onFound(UsbPrinter usbPrinter) {
}
@Override
public void onFinished(List<UsbPrinter> usbPrinters) {
mUsbPrinters = usbPrinters;
}
});
//開啟監聽USB連接
printerFinder.startFinder();
}
/**
* 請求prj數據
*/
public void getPrjInfo() {
OkHttp3Utils.get(HttpsConstans.ROOT_SERVER_ADDRESS_FORMAL + "printerRecording/get?restaurantId=" + RestaurantInfoManager.newInstance().getRestaurantId())
.subscribeOn(Schedulers.io())//切换到io线程進行網絡請求
.observeOn(Schedulers.io())//切換到io线程處理請求結果
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
LoganManager.w_printer(TAG, "獲取Prj數據 Disposable");
}
@Override
public void onNext(String prjInfo) {
LoganManager.w_printer(TAG, "獲取Prj數據 onNext: " + prjInfo);
//請求到數據,停止輪詢,開始打印,在打印完之後再重新開始輪詢
actionPrint(prjInfo);
}
@Override
public void onError(Throwable e) {
LoganManager.w_printer(TAG, "獲取Prj數據 onError:" + e.getMessage());
}
@Override
public void onComplete() {
LoganManager.w_printer(TAG, "獲取Prj數據 onComplete");
}
});
}
public void actionPrint(String json) {
if (TextUtils.isEmpty(json)) {
return;
}
Map<String, List<PrjBean.DataBean.Bean>> listMap = new HashMap<>();
currentIndex = 0;
totalPrj = 0;
PrjBean prjBean = JsonUtils.parseObject(json, PrjBean.class);
if (prjBean == null || prjBean.getData() == null) {
LoganManager.w_printer(TAG, "newPrint prjBean == null || prjBean.getData() == null ");
return;
}
//第一步:解析PRJ數據,格式為 Map<廚房位置,需要打印的數據>
try {
JSONObject jsonObject = new JSONObject(prjBean.getData());
//通过迭代器获取这段json当中所有的key值
Iterator keys = jsonObject.keys();
//然后通过一个循环取出所有的key值
while (keys.hasNext()) {
String key = String.valueOf(keys.next());
//最后就可以通过刚刚得到的key值去解析后面的json了
JSONArray dataJson = (JSONArray) jsonObject.get(key);
List<PrjBean.DataBean.Bean> datas = JsonUtils.parseArray(dataJson.toString(), PrjBean.DataBean.Bean.class);
if (datas != null && datas.size() > 0) {
//打印位置和需要打印的數據
listMap.put(key, datas);
//計算本次打印的prj總張數有沒有不需要切紙的
boolean isHasNoCut = false;
for (PrjBean.DataBean.Bean bean : datas) {
if (bean.getStatus() == 2) {
//需要切紙,prj總數就+1
totalPrj++;
} else {
isHasNoCut = true;
}
}
if (isHasNoCut) {
//有不需要切紙的食物,prj總數+1
totalPrj++;
}
}
}
} catch (JSONException e) {
e.printStackTrace();
LoganManager.w_printer(TAG, "newPrint JSONException: " + e.getMessage());
}
setPrjIndex(listMap, totalPrj);
foreachPrint(listMap, getPrinterDevices());
}
private Map<String, List<PrjBean.DataBean.Bean>> setPrjIndex(Map<String, List<PrjBean.DataBean.Bean>> listMap, int totalPrj) {
for (Map.Entry<String, List<PrjBean.DataBean.Bean>> prjMap : listMap.entrySet()) {
//上一個對象是否切紙
boolean lastIsCute = false;
for (PrjBean.DataBean.Bean bean : prjMap.getValue()) {
bean.setTotalPrj(totalPrj);
if (bean.getStatus() == 2) {
//要切紙,紙張數+1
currentIndex++;
lastIsCute = true;
} else {
if (currentIndex == 0) {
currentIndex = 1;
} else if (lastIsCute) {
//如果上一張切紙,那這一張下標就要+1
currentIndex++;
}
lastIsCute = false;
}
bean.setCurrentIndex(currentIndex);
}
currentIndex++;
}
return listMap;
}
private void foreachPrint(Map<String, List<PrjBean.DataBean.Bean>> listMap, List<PrinterDeviceBean> printerDeviceBeans) {
//雙重遍歷可以以後優化
//第二步:遍歷 Map<廚房位置,需要打印的數據>,通過廚房位置找到對應的打印機,並且通過數據拿到對應的通用配置
for (Map.Entry<String, List<PrjBean.DataBean.Bean>> prjMap : listMap.entrySet()) {
boolean isFindDevice = false;
for (PrinterDeviceBean deviceBean : printerDeviceBeans) {
//遍歷得到當前打印機,如果沒找到打印機,就不打印
if (prjMap.getKey().toLowerCase().equals(deviceBean.getName().toLowerCase())) {
isFindDevice = true;
//如果PRJ數據的廚房位置和打印機名稱相同,則就是這台打印機打印
//通過需要打印的數據,得到通用配置
PrintCurrencyBean printCurrencyBean = getPrintCurrencyBean(prjMap.getValue());
//將通用配置設置給了對應的打印機對象後,得到新的打印機對象
PrinterDeviceBean configPrinterDeviceBean = MyPrintUtils.configPrinterProperties(printCurrencyBean, deviceBean);
// 判斷打印機的類型,調用不同的打印方式,
// 這裡已經拿到這台打印機需要打印的所有數據,為prjMp.getValue(),
// 生成對應的打印數據,除了針式打印機,其他都生成bitmap
generatePrintData(prjMap.getKey(), prjMap.getValue(), configPrinterDeviceBean);
}
}
if (!isFindDevice) {
//用戶沒有這個打印機,打印失敗,返回後台原因
updatePrjState(UpdateBean.FAIL_PRINT_BY_NOT_FIND_DEVICE, getPrintIdsByPrjData(prjMap.getValue()));
}
}
}
/**
* 獲取打印設備
*
* @return 打印機列表
*/
private List<PrinterDeviceBean> getPrinterDevices() {
//讀取打印機和通用配置,可以優化
//獲取所有打印機
PrinterDeviceDaoUtils printerDeviceDaoUtils = new PrinterDeviceDaoUtils(mContext);
LoganManager.w_printer(TAG, "获取打印設備信息");
return printerDeviceDaoUtils.queryAllPrinterDeviceBean();
}
/**
* 獲取通用打印配置
*
* @param beans prj數據
* @return 通用配置
*/
private PrintCurrencyBean getPrintCurrencyBean(List<PrjBean.DataBean.Bean> beans) {
PrintCurrencyBean printCurrencyBean = null;
if (beans != null && beans.size() > 0) {
if (beans.get(0).getOrderType() == 1 || beans.get(0).getOrderType() == 3) {
//堂食,skyorder
printCurrencyBean = MyPrintUtils.getPrintCurrencyBeanByType(mContext, 1);
} else {
//外賣
printCurrencyBean = MyPrintUtils.getPrintCurrencyBeanByType(mContext, 2);
}
}
return printCurrencyBean;
}
/**
* 生成用於打印的prj的Bitmap
*/
private void generatePrintData(String key, List<PrjBean.DataBean.Bean> beans, PrinterDeviceBean printerDeviceBean) {
int orderType = 1;
if (beans != null && beans.size() > 0) {
orderType = beans.get(0).getOrderType();
}
PrinterPlugins.getOnPrinterFlowHandler().onPrinterDataBefore(orderType, PrintConstans.PRINT_KITCHEN, GsonUtils.GsonString(beans), GsonUtils.GsonString(printerDeviceBean));
if (isPinPrinter(printerDeviceBean) && printerDeviceBean.getPrinterDeviceType() == PRINT_IP) {
//針式打印
stylusPrinting(key, beans, printerDeviceBean);
} else if (printerDeviceBean.getPrinterDeviceType() == PRINT_PRJ_PC) {
//prj模式,生成文件到共享電腦上
prjToPc(beans, printerDeviceBean);
} else if (printerDeviceBean.getPrinterDeviceType() == PRINT_LOCAL && PrintConstans.PRINT_MODEL_WISEPOS.contains(Build.MODEL)) {
//本機打印並且是BBPOS
} else {
List<Map<String, Bitmap>> bitmapMaps = generatePrintMaps(key, beans, printerDeviceBean);
switch (printerDeviceBean.getPrinterDeviceType()) {
case PRINT_IP:
LoganManager.w_printer(TAG, "開始IP打印-->");
//IP打印
ipPrint(printerDeviceBean, bitmapMaps);
break;
case PRINT_LOCAL:
//本地N5或Sunmi打印
locationPrint(bitmapMaps);
break;
case PRINT_USB:
LoganManager.w_printer(TAG, "開始USB打印-->");
//USB打印
usbPrint(bitmapMaps);
break;
default:
break;
}
}
}
/**
* PRJ模式,生成PRJ文件到共享的電腦上
*
* @param beans prj數據
* @param printerDeviceBean 打印設備
*/
private void prjToPc(List<PrjBean.DataBean.Bean> beans, PrinterDeviceBean printerDeviceBean) {
//PRJ模式,生成PRJ文件到共享的電腦上
ThreadPoolManager.getInstence().putExecutableTasks(() -> {
List<PrjBean.DataBean.Bean> noCutList = new ArrayList<>();
List<PrjBean.DataBean.Bean> cutList = new ArrayList<>();
for (PrjBean.DataBean.Bean bean : beans) {
if (bean.getStatus() == 2) {
//需要切紙
cutList.add(bean);
} else {
//不需要切紙
noCutList.add(bean);
}
}
String rootPath = "smb://" + printerDeviceBean.getPrintPath() + "/";
try {
SmbFile smbFile = new SmbFile(rootPath);
smbFile.connect();
if (smbFile.isDirectory()) {
for (int i = 0; i < cutList.size(); i++) {
String newFilePath = rootPath + System.currentTimeMillis() + ".prj";
SmbFile createFile = new SmbFile(newFilePath);
createFile.createNewFile();
if (createFile.exists()) {
PrintStream ps = new PrintStream(new SmbFileOutputStream(createFile));
// 往文件里写入字符串
String prjInfo = "[printType]ptKitchen\n" +
"[table]4\n" +
"[date]落單時間:11-13 17:48\n" +
"[waiter]n5 收銀員\n" +
"[KP]K2烤爐\n" +
"[PAX]人數:2\n" +
"[line]\n" +
"[food_1]1 包子(主項)\n" +
"[food_1]1 包子(主項)\n" +
"[table2]4\n";
ps.println(prjInfo);
}
}
if (noCutList.size() > 0) {
String newFilePath = rootPath + System.currentTimeMillis() + ".prj";
SmbFile createFile = new SmbFile(newFilePath);
createFile.createNewFile();
if (createFile.exists()) {
PrintStream ps = new PrintStream(new SmbFileOutputStream(createFile));
PrjBean.DataBean.Bean bean = noCutList.get(0);
String tableName = "";
if (TextUtil.isEmptyOrNullOrUndefined(bean.getTableName())) {
if (bean.getOrderType() == 7) {
tableName = "自取";
} else {
tableName = "外賣";
}
} else {
tableName = bean.getTableName();
}
// 往文件里写入字符串
// String prjInfo = "[printType]ptKitchen\n" +
// "[table]4\n" +
// "[date]落單時間:11-13 17:48\n" +
// "[waiter]n5 收銀員\n" +
// "[KP]K2烤爐\n" +
// "[PAX]人數:2\n" +
// "[line]\n" +
// "[food_1]1 包子(主項)\n" +
// "[food_1]1 包子(主項)\n" +
// "[table2]4\n";
String prjInfo = "[printType]ptKitchen\n" +
"[table]" + tableName + "\n" +
"[date]落單時間:11-13 17:48\n" +
"[waiter]n5 收銀員\n" +
"[KP]K2烤爐\n" +
"[PAX]人數:2\n" +
"[line]\n" +
"[food_1]1 包子(主項)\n" +
"[food_1]1 包子(主項)\n" +
"[table2]" + tableName + "\n";
ps.println(prjInfo);
}
}
} else {
ToastUtils.show(mContext, "PRJ輸出路徑必須為文件夾");
}
} catch (IOException e) {
e.printStackTrace();
}
});
}
/**
* 針式打印機
*
* @param key 廚房位置
* @param beans prj數據
* @param printerDeviceBean 打印機
*/
private void stylusPrinting(String key, List<PrjBean.DataBean.Bean> beans, PrinterDeviceBean printerDeviceBean) {
//針式打印機並且打印機類型為IP打印,生成獨特的格式
List<Map<String, Bitmap>> bitmapMaps = generatePrintMaps(key, beans, printerDeviceBean);
//將打印的圖片保存到手機中
hookPrinterBitmap(bitmapMaps, beans);
boolean initResult = EpsonPrint.getInstance().initializeObject(mContext, this, errorCode -> updatePrjState(errorCode, getPrintIds(bitmapMaps)));
if (!initResult) {
//初始化打印機失敗
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new ConnectException("初始化針式打印機失敗"));
updatePrjState(UpdateBean.FAIL_EPSON_INIT, getPrintIds(bitmapMaps));
return;
}
PrinterPlugins.getOnPrinterFlowHandler().connectionBefore("針式打印機" + bitmapMaps.size(), printerDeviceBean.getIp(), printerDeviceBean.getPort(), 0, 0);
Log.d("eee", "針式打印機本次PRJ數量:" + bitmapMaps.size());
for (int i = 0; i < bitmapMaps.size(); i++) {
for (Map.Entry<String, Bitmap> mapEntry : bitmapMaps.get(i).entrySet()) {
EpsonPrint.getInstance().putPrintData(printerDeviceBean.getIp(), mapEntry.getValue(), mapEntry.getKey());
}
}
}
/**
* ip設備打印
*/
public void ipPrint(PrinterDeviceBean printerDeviceBean, List<Map<String, Bitmap>> bitmapMaps) {
for (int i = 0; i < bitmapMaps.size(); i++) {
// if (executor == null) {
// executor = new PrintExecutor().setOnPrjPrintResultListener((errorCode, ids) -> {
// switch (errorCode) {
// case PrintSocketHolder.ERROR_0:
// //更新狀態
// updatePrjSuccess(ids);
// break;
// case PrintSocketHolder.ERROR_2:
// updatePrjFailure(ids);
// break;
// }
// });
// }
// PrjPrintMaker maker = new PrjPrintMaker(bitmapMaps.get(i), printerDeviceBean.getIp(), printerDeviceBean.getPort());
// executor.doPrinterRequestAsync(maker);
PrintExecutor.getInstance().setOnPrjPrintResultListener(this::updatePrjState);
PrjPrintMaker maker = new PrjPrintMaker(bitmapMaps.get(i), printerDeviceBean.getIp(), printerDeviceBean.getPort());
PrintExecutor.getInstance().doPrinterRequestAsync(maker);
}
}
/**
* usb打印
*/
public void usbPrint(List<Map<String, Bitmap>> bitmapMaps) {
for (int i = 0; i < bitmapMaps.size(); i++) {
for (Map.Entry<String, Bitmap> bitmapMap : bitmapMaps.get(i).entrySet()) {
final String key = bitmapMap.getKey();
UsbPrint usbPrint = new UsbPrint(mContext, (code, printId) -> {
//打印結果
if (code == SendResultCode.SEND_SUCCESS) {
PrinterPlugins.getOnPrinterFlowHandler().onPrintSuccess();
updatePrjSuccess(key);
} else if (code == SendResultCode.SEND_FAILED) {
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception("發送打印數據失敗"), code);
updatePrjFailure(key);
}
});
if (mUsbPrinters != null && mUsbPrinters.size() > 0) {
EscCommand esc = new EscCommand();
ArrayList<byte[]> bytes = new ArrayList<>();
try {
bytes.addAll(new PrinterWriter58mm().getImageByte(bitmapMap.getValue()));
} catch (IOException e) {
e.printStackTrace();
}
bytes.add(esc.getPrintAndFeedLines((byte) 8));
bytes.add(esc.getCutPaper());
bytes.add(esc.getCleanCache());
usbPrint.sendPrintCommand(mUsbPrinters.get(0), bytes);
} else {
//打印失敗
updatePrjFailure(key);
}
}
}
}
/**
* 本機打印
*/
public void locationPrint(List<Map<String, Bitmap>> bitmapMaps) {
String model = Build.MODEL;
if (PrintConstans.PRINT_MODEL_V2.contains(model)) {
//商米打印
LoganManager.w_printer(TAG, "開始商米打印-->");
sunmiPrint(bitmapMaps);
} else if (PrintConstans.PRINT_MODEL_N5.contains(model)) {
//N5打印
LoganManager.w_printer(TAG, "開始N5打印-->");
n5Print(bitmapMaps);
} else if (PrintConstans.PRINT_MODEL_WISEPOS.contains(model)) {
//BBPOS,生成data
ToastUtils.show(mContext, "BBPOS不支持打印廚房單");
} else {
updatePrjState(UpdateBean.FAIL_LOCAL_PRINT_NOT_DEVICE, getPrintIds(bitmapMaps));
}
}
/**
* 獲取本次打印的prj id
*
* @return prj的id集合
*/
private String getPrintIdsByPrjData(List<PrjBean.DataBean.Bean> prjBeans) {
StringBuilder stringBuilder = new StringBuilder();
for (PrjBean.DataBean.Bean prjBean : prjBeans) {
stringBuilder.append(prjBean.getId());
if (stringBuilder.toString().lastIndexOf(",") != stringBuilder.length() - 1) {
//如果最後一位不是逗號,才添加
stringBuilder.append(",");
}
}
return stringBuilder.toString();
}
/**
* 獲取本次打印的prj id
*
* @param bitmapMaps
* @return
*/
private String getPrintIds(List<Map<String, Bitmap>> bitmapMaps) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < bitmapMaps.size(); i++) {
for (Map.Entry<String, Bitmap> mapEntry : bitmapMaps.get(i).entrySet()) {
stringBuilder.append(mapEntry.getKey()).append(",");
}
}
if (stringBuilder.length() <= 0) {
return "";
}
//最後一位是逗號,去掉
return stringBuilder.substring(0, stringBuilder.length() - 1);
}
/**
* 商米打印
*/
private void sunmiPrint(List<Map<String, Bitmap>> bitmapMaps) {
//商米打印
for (int i = 0; i < bitmapMaps.size(); i++) {
for (Map.Entry<String, Bitmap> mapEntry : bitmapMaps.get(i).entrySet()) {
final String ids = mapEntry.getKey();
AidlUtil.getInstance().printBitmap(mapEntry.getValue(), new InnerResultCallbcak() {
@Override
public void onRunResult(boolean isSuccess) {
LoganManager.w_printer(TAG, "商米onRunResult: " + isSuccess);
//返回接⼝执⾏的情况(并⾮真实打印):成功或失败
if (isSuccess) {
updatePrjSuccess(ids);
} else {
updatePrjFailure(ids);
}
}
@Override
public void onReturnString(String result) {
//部分接⼝会异步返回查询数据
LoganManager.w_printer(TAG, "商米onReturnString: " + result);
}
@Override
public void onRaiseException(int code, String msg) {
//接⼝执⾏失败时,返回的异常状态
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception(msg), code);
LoganManager.w_printer(TAG, "商米onRaiseException: " + code + msg);
switch (code) {
case 3:
//通訊異常
updatePrjState(UpdateBean.FAIL_PRINT_BY_NOT_CONNECT, ids);
break;
case 4:
//缺紙
updatePrjState(UpdateBean.FAIL_NOT_PAPER, ids);
break;
case 5:
//過熱
updatePrjState(UpdateBean.FAIL_SUNMI_PRINT_HOT, ids);
break;
case 6:
//蓋子未合上
updatePrjState(UpdateBean.FAIL_LID_NOT_CLOSED_SUNMI, ids);
break;
case 7:
//切刀異常
updatePrjState(UpdateBean.FAIL_CUT_ABNORMAL_SUNMI, ids);
break;
case 9:
//黑標異常
updatePrjState(UpdateBean.FAIL_SUNMI_NO_BLACK_MARK_DETECTED, ids);
break;
default:
updatePrjState(UpdateBean.FAIL_PRINT_BY_NOT_FIND_DEVICE_SUNMI, ids);
break;
}
}
@Override
public void onPrintResult(int code, String msg) {
//事务模式下真实的打印结果返回
LoganManager.w_printer(TAG, "商米onPrintResult: " + msg);
}
});
}
}
}
/**
* n5打印
*/
private void n5Print(List<Map<String, Bitmap>> bitmapMaps) {
for (int i = 0; i < bitmapMaps.size(); i++) {
for (Map.Entry<String, Bitmap> mapEntry : bitmapMaps.get(i).entrySet()) {
final String ids = mapEntry.getKey();
try {
PrinterUtil.appendImage(mapEntry.getValue(), PrinterConstant.ALIGN_CENTER);
PrinterUtil.appendPrnStr("\n", 24, PrinterConstant.ALIGN_CENTER, false);
PrinterUtil.appendPrnStr("\n", 24, PrinterConstant.ALIGN_CENTER, false);
PrinterUtil.startPrint(true, new IOnPrintCallback.Stub() {
@Override
public void onPrintResult(int i) {
LoganManager.w_printer(TAG, "N5 onPrintResult: " + i);
if (i == 0) {
//打印成功
updatePrjSuccess(ids);
} else {
//打印失敗
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception(UpdateBean.getStateByCode(i)), i);
updatePrjState(i, ids);
}
}
@Override
public IBinder asBinder() {
LoganManager.w_printer(TAG, "N5 asBinder");
return this;
}
});
} catch (RemoteException e) {
e.printStackTrace();
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(e, i);
LoganManager.w_printer(TAG, "N5 RemoteException :" + e.getLocalizedMessage());
updatePrjFailure(ids);
}
}
}
}
/**
* 生成打印需要的Map集合,Map的key是這張PRJ的所有PRJ記錄的id,然後會同時打印多張,所以是一個List集合
*
* @param key 打印位置
* @param beans 打印的食品和其他的一些信息
*/
private List<Map<String, Bitmap>> generatePrintMaps(String key, List<PrjBean.DataBean.Bean> beans, PrinterDeviceBean printerDeviceBean) {
PrintPrjKitchen printPrjKitchen = new PrintPrjKitchen();
//這個Map的key是這張PRJ的所有PRJ記錄的id,然後會同時打印多張,所以是一個List集合
List<Map<String, Bitmap>> bitmapMaps = new ArrayList<>();
List<PrjBean.DataBean.Bean> noCut = new ArrayList<>();
//不帶*號,所有同樣廚房位置的食品都在一張紙上
for (PrjBean.DataBean.Bean bean : beans) {
if (bean.getStatus() == 2) {
Map<String, Bitmap> map = new HashMap<>();
//帶*,需要切紙的,單獨放一張紙
map.put(bean.getId() + "", printPrjKitchen.getKitChenPrintBitmap(mContext, key, bean, printerDeviceBean));
bitmapMaps.add(map);
} else {
noCut.add(bean);
}
}
if (noCut.size() > 0) {
Map<String, Bitmap> map = new HashMap<>();
//遍歷拿到這張紙所有的PRJ記錄ID
StringBuilder stringBuffer = new StringBuilder();
for (PrjBean.DataBean.Bean noCutData : noCut) {
stringBuffer.append(noCutData.getId());
stringBuffer.append(",");
}
Bitmap prjBitmap = printPrjKitchen.getKitChenPrintBitmap(mContext, key, noCut, printerDeviceBean);
map.put(stringBuffer.toString(), prjBitmap);
bitmapMaps.add(map);
}
hookPrinterBitmap(bitmapMaps, beans);
return bitmapMaps;
}
private void hookPrinterBitmap(List<Map<String, Bitmap>> bitmapMaps, List<PrjBean.DataBean.Bean> beans) {
if (bitmapMaps.size() > 0) {
String prjName = String.valueOf(System.currentTimeMillis());
int orderType = 1;
if (beans.size() > 0) {
PrjBean.DataBean.Bean prjBean = beans.get(0);
if (prjBean != null) {
if (!TextUtils.isEmpty(prjBean.getBillNo())) {
prjName = prjBean.getBillNo();
} else {
prjName = prjBean.getOrderNo();
}
orderType = prjBean.getOrderType();
}
}
List<Bitmap> bitmapList = new ArrayList<>();
for (int i = 0; i < bitmapMaps.size(); i++) {
Set<Map.Entry<String, Bitmap>> bitmapSet = bitmapMaps.get(i).entrySet();
Iterator<Map.Entry<String, Bitmap>> bitmapIterator = bitmapSet.iterator();
while (bitmapIterator.hasNext()) {
bitmapList.add(bitmapIterator.next().getValue());
}
}
PrinterPlugins.getOnPrinterFlowHandler().onPrinterBitmapBefore(orderType, PrintConstans.PRINT_KITCHEN, prjName, bitmapList);
}
}
/**
* 是否為針式打印機
*
* @param printerDeviceBean 打印機實體類
* @return true是
*/
private boolean isPinPrinter(PrinterDeviceBean printerDeviceBean) {
return (printerDeviceBean != null && printerDeviceBean.getPrinterName() != null && printerDeviceBean.getPrinterName().toLowerCase().contains("EPSON".toLowerCase()))
&& (printerDeviceBean.getModel() != null && printerDeviceBean.getModel().toLowerCase().contains("TM-U220B".toLowerCase()));
}
private void updatePrjSuccess(String ids) {
updatePrjState(UpdateBean.ALREADY_PRINT, ids);
}
/**
* 打印失敗,將打印狀態改為未打印,並不是改為打印失敗,失敗是由後台判斷打印失敗次數超過最大限制之後改為打印失敗的
*
* @param ids prj的id集合
*/
private void updatePrjFailure(String ids) {
updatePrjState(UpdateBean.NO_PRINT, ids);
}
/**
* @param printState 打印狀態 1未打印 2打印中 3已打印
*/
private void updatePrjState(int printState, String ids) {
Long time = null;
if (printState == 3) {
time = TimeUtils.getCurrentTimeInLong();
}
List<UpdateBean> updateBeans = new ArrayList<>();
String[] idArrays = ids.split(",");
for (String id : idArrays) {
updateBeans.add(new UpdateBean(id, printState, time));
}
String json = JsonUtils.toJson(updateBeans);
Log.e(TAG, "修改打印狀態:" + json);
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), json);
OkHttp3Utils.post(HttpsConstans.ROOT_SERVER_ADDRESS_FORMAL + "printerRecording/update", requestBody)
.subscribeOn(Schedulers.io())//切换到io线程進行網絡請求
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
LoganManager.w_printer(TAG, "修改Prj打印狀態---end----: " + json + s);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
@Override
public void onPtrReceive(Printer printer, int i, PrinterStatusInfo printerStatusInfo, String s) {
//針式打印回調
if (i == 0) {
PrinterPlugins.getOnPrinterFlowHandler().onPrintSuccess();
//打印成功
updatePrjSuccess(s);
} else {
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception("打印失敗"), i);
//打印失敗
updatePrjFailure(s);
}
}
}
...@@ -50,6 +50,7 @@ import com.gingersoft.gsa.cloud.print.PrinterWriter58mm; ...@@ -50,6 +50,7 @@ import com.gingersoft.gsa.cloud.print.PrinterWriter58mm;
import com.gingersoft.gsa.cloud.print.bean.PrintContent; import com.gingersoft.gsa.cloud.print.bean.PrintContent;
import com.gingersoft.gsa.cloud.print.bean.PrintTakeawayCheckoutContent; import com.gingersoft.gsa.cloud.print.bean.PrintTakeawayCheckoutContent;
import com.gingersoft.gsa.cloud.print.bean.PrintTakeawayFormContent; import com.gingersoft.gsa.cloud.print.bean.PrintTakeawayFormContent;
import com.gingersoft.gsa.cloud.print.bean.UpdateBean;
import com.gingersoft.gsa.cloud.print.bean.base.PrintBillItem; import com.gingersoft.gsa.cloud.print.bean.base.PrintBillItem;
import com.gingersoft.gsa.cloud.print.bean.base.PrintFoodItem; import com.gingersoft.gsa.cloud.print.bean.base.PrintFoodItem;
import com.gingersoft.gsa.cloud.print.bean.base.PrintPayTypeItem; import com.gingersoft.gsa.cloud.print.bean.base.PrintPayTypeItem;
...@@ -283,7 +284,7 @@ public abstract class PrinterRoot<T extends PrintContent> implements PrintSocket ...@@ -283,7 +284,7 @@ public abstract class PrinterRoot<T extends PrintContent> implements PrintSocket
@Override @Override
public void onRaiseException(int code, String msg) { public void onRaiseException(int code, String msg) {
//接⼝执⾏失败时,返回的异常状态 //接⼝执⾏失败时,返回的异常状态
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(null, code); PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception(msg), code);
LoganManager.w_printer(TAG, "商米onRaiseException: " + code + msg); LoganManager.w_printer(TAG, "商米onRaiseException: " + code + msg);
} }
...@@ -308,7 +309,7 @@ public abstract class PrinterRoot<T extends PrintContent> implements PrintSocket ...@@ -308,7 +309,7 @@ public abstract class PrinterRoot<T extends PrintContent> implements PrintSocket
} else { } else {
//打印失敗 //打印失敗
listener.printFailure("打印失敗"); listener.printFailure("打印失敗");
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(null, i); PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception(UpdateBean.getStateByCode(i)), i);
} }
} }
...@@ -370,6 +371,7 @@ public abstract class PrinterRoot<T extends PrintContent> implements PrintSocket ...@@ -370,6 +371,7 @@ public abstract class PrinterRoot<T extends PrintContent> implements PrintSocket
if (code == SendResultCode.SEND_SUCCESS) { if (code == SendResultCode.SEND_SUCCESS) {
printSuccess(); printSuccess();
} else if (code == SendResultCode.SEND_FAILED) { } else if (code == SendResultCode.SEND_FAILED) {
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception("usb打印失敗"), 0);
printFailure("打印失敗"); printFailure("打印失敗");
} }
}); });
...@@ -440,7 +442,6 @@ public abstract class PrinterRoot<T extends PrintContent> implements PrintSocket ...@@ -440,7 +442,6 @@ public abstract class PrinterRoot<T extends PrintContent> implements PrintSocket
@Override @Override
public void onResult(int errorCode) { public void onResult(int errorCode) {
Log.e("eee", "打印結果:" + errorCode);
switch (errorCode) { switch (errorCode) {
case PrintSocketHolder.ERROR_0: case PrintSocketHolder.ERROR_0:
PrinterPlugins.getOnPrinterFlowHandler().onPrintSuccess(); PrinterPlugins.getOnPrinterFlowHandler().onPrintSuccess();
...@@ -448,25 +449,31 @@ public abstract class PrinterRoot<T extends PrintContent> implements PrintSocket ...@@ -448,25 +449,31 @@ public abstract class PrinterRoot<T extends PrintContent> implements PrintSocket
return; return;
case PrintSocketHolder.ERROR_6: case PrintSocketHolder.ERROR_6:
LoganManager.w_printer(TAG, "生成打印數據失敗"); LoganManager.w_printer(TAG, "生成打印數據失敗");
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new Exception("生成打印數據失敗"));
printFailure("生成打印數據失敗"); printFailure("生成打印數據失敗");
break; break;
case PrintSocketHolder.ERROR_7: case PrintSocketHolder.ERROR_7:
LoganManager.w_printer(TAG, "連接打印機失敗"); LoganManager.w_printer(TAG, "連接打印機失敗");
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new Exception("連接打印機失敗"));
printFailure("連接打印機失敗"); printFailure("連接打印機失敗");
break; break;
case PrintSocketHolder.ERROR_10: case PrintSocketHolder.ERROR_10:
LoganManager.w_printer(TAG, "連接打印機失敗(写入页面数据失败),Code:" + PrintSocketHolder.ERROR_10); LoganManager.w_printer(TAG, "打印機連接成功,發送數據出現問題" );
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception("打印機連接成功,發送數據出現問題"), errorCode);
printFailure("打印失敗,錯誤碼:" + errorCode); printFailure("打印失敗,錯誤碼:" + errorCode);
break; break;
case PrintSocketHolder.ERROR_9: case PrintSocketHolder.ERROR_9:
LoganManager.w_printer(TAG, "連接打印機失敗(必要参数不能为空)"); LoganManager.w_printer(TAG, "IP地址為空");
printFailure("連接打印機失敗,沒有ip地址,錯誤碼:" + errorCode); PrinterPlugins.getOnPrinterFlowHandler().connectionError(new Exception("IP地址為空"));
printFailure("IP地址為空");
break; break;
case PrintSocketHolder.ERROR_66: case PrintSocketHolder.ERROR_66:
LoganManager.w_printer(TAG, "关闭Socket出错"); LoganManager.w_printer(TAG, "關閉Socket出錯");
PrinterPlugins.getOnPrinterFlowHandler().disconnect(new Exception("關閉打印機連接出错"));
break;
default:
break; break;
} }
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(null, errorCode);
setPrintState(errorCode); setPrintState(errorCode);
} }
......
...@@ -59,6 +59,7 @@ import org.json.JSONObject; ...@@ -59,6 +59,7 @@ import org.json.JSONObject;
import java.io.IOException; import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.net.ConnectException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
...@@ -221,7 +222,6 @@ public class PrjService extends Service implements ReceiveListener { ...@@ -221,7 +222,6 @@ public class PrjService extends Service implements ReceiveListener {
private int totalPrj; private int totalPrj;
private int currentIndex; private int currentIndex;
private String prjJson = "{\"success\":true,\"sysTime\":1613789540248,\"data\":{\"K1\":[{\"id\":71387,\"printerDeviceId\":186,\"status\":2,\"tableName\":\"堂食1\",\"orderNo\":\"0013\",\"orderTime\":2021,\"person\":1,\"number\":1,\"orderDetailsTime\":\"Feb 23, 2021 1:52:06 PM\",\"orderDetailsId\":372,\"productName\":\"N1. Mr.Arita華盛丼>得獎和牛使用定食\",\"productName2\":\"\",\"productName3\":\"\",\"parentId\":0,\"type\":3,\"createTime\":1614059526281,\"productId\":61256,\"requests\":1,\"actualPrinterDeviceId\":186,\"orderType\":1,\"isFirstSendOrder\":1,\"quantity\":21,\"memberName\":\"96761128\"}]}}";
private void newPrint(String json) { private void newPrint(String json) {
Map<String, List<PrjBean.DataBean.Bean>> listMap = new HashMap<>(); Map<String, List<PrjBean.DataBean.Bean>> listMap = new HashMap<>();
...@@ -513,10 +513,10 @@ public class PrjService extends Service implements ReceiveListener { ...@@ -513,10 +513,10 @@ public class PrjService extends Service implements ReceiveListener {
//將打印的圖片保存到手機中 //將打印的圖片保存到手機中
hookPrinterBitmap(bitmapMaps, beans); hookPrinterBitmap(bitmapMaps, beans);
EpsonPrint mPrinter = EpsonPrint.getInstance();
boolean initResult = EpsonPrint.getInstance().initializeObject(this, this, errorCode -> updatePrjState(errorCode, getPrintIds(bitmapMaps))); boolean initResult = EpsonPrint.getInstance().initializeObject(this, this, errorCode -> updatePrjState(errorCode, getPrintIds(bitmapMaps)));
if (!initResult) { if (!initResult) {
//初始化打印機失敗 //初始化打印機失敗
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new ConnectException("初始化針式打印機失敗"));
updatePrjState(UpdateBean.FAIL_EPSON_INIT, getPrintIds(bitmapMaps)); updatePrjState(UpdateBean.FAIL_EPSON_INIT, getPrintIds(bitmapMaps));
return; return;
} }
...@@ -524,7 +524,7 @@ public class PrjService extends Service implements ReceiveListener { ...@@ -524,7 +524,7 @@ public class PrjService extends Service implements ReceiveListener {
Log.d("eee", "針式打印機本次PRJ數量:" + bitmapMaps.size()); Log.d("eee", "針式打印機本次PRJ數量:" + bitmapMaps.size());
for (int i = 0; i < bitmapMaps.size(); i++) { for (int i = 0; i < bitmapMaps.size(); i++) {
for (Map.Entry<String, Bitmap> mapEntry : bitmapMaps.get(i).entrySet()) { for (Map.Entry<String, Bitmap> mapEntry : bitmapMaps.get(i).entrySet()) {
mPrinter.putPrintData(printerDeviceBean.getIp(), mapEntry.getValue(), mapEntry.getKey()); EpsonPrint.getInstance().putPrintData(printerDeviceBean.getIp(), mapEntry.getValue(), mapEntry.getKey());
} }
} }
} }
...@@ -568,7 +568,7 @@ public class PrjService extends Service implements ReceiveListener { ...@@ -568,7 +568,7 @@ public class PrjService extends Service implements ReceiveListener {
PrinterPlugins.getOnPrinterFlowHandler().onPrintSuccess(); PrinterPlugins.getOnPrinterFlowHandler().onPrintSuccess();
updatePrjSuccess(key); updatePrjSuccess(key);
} else if (code == SendResultCode.SEND_FAILED) { } else if (code == SendResultCode.SEND_FAILED) {
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(null, code); PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception("發送打印數據失敗"), code);
updatePrjFailure(key); updatePrjFailure(key);
} }
}); });
...@@ -679,7 +679,7 @@ public class PrjService extends Service implements ReceiveListener { ...@@ -679,7 +679,7 @@ public class PrjService extends Service implements ReceiveListener {
@Override @Override
public void onRaiseException(int code, String msg) { public void onRaiseException(int code, String msg) {
//接⼝执⾏失败时,返回的异常状态 //接⼝执⾏失败时,返回的异常状态
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(null, code); PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception(msg), code);
LoganManager.w_printer(TAG, "商米onRaiseException: " + code + msg); LoganManager.w_printer(TAG, "商米onRaiseException: " + code + msg);
switch (code) { switch (code) {
case 3: case 3:
...@@ -742,8 +742,8 @@ public class PrjService extends Service implements ReceiveListener { ...@@ -742,8 +742,8 @@ public class PrjService extends Service implements ReceiveListener {
updatePrjSuccess(ids); updatePrjSuccess(ids);
} else { } else {
//打印失敗 //打印失敗
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception(UpdateBean.getStateByCode(i)), i);
updatePrjState(i, ids); updatePrjState(i, ids);
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(null, i);
} }
} }
...@@ -755,6 +755,7 @@ public class PrjService extends Service implements ReceiveListener { ...@@ -755,6 +755,7 @@ public class PrjService extends Service implements ReceiveListener {
}); });
} catch (RemoteException e) { } catch (RemoteException e) {
e.printStackTrace(); e.printStackTrace();
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(e, i);
LoganManager.w_printer(TAG, "N5 RemoteException :" + e.getLocalizedMessage()); LoganManager.w_printer(TAG, "N5 RemoteException :" + e.getLocalizedMessage());
updatePrjFailure(ids); updatePrjFailure(ids);
} }
...@@ -904,7 +905,7 @@ public class PrjService extends Service implements ReceiveListener { ...@@ -904,7 +905,7 @@ public class PrjService extends Service implements ReceiveListener {
//打印成功 //打印成功
updatePrjSuccess(s); updatePrjSuccess(s);
} else { } else {
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(null, i); PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception("打印失敗"), i);
//打印失敗 //打印失敗
updatePrjFailure(s); updatePrjFailure(s);
} }
......
package com.joe.print.mvp.ui.activity; package com.joe.print.mvp.ui.activity;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
...@@ -25,12 +27,14 @@ import com.gingersoft.gsa.cloud.common.utils.other.TextUtil; ...@@ -25,12 +27,14 @@ import com.gingersoft.gsa.cloud.common.utils.other.TextUtil;
import com.gingersoft.gsa.cloud.common.utils.toast.ToastUtils; import com.gingersoft.gsa.cloud.common.utils.toast.ToastUtils;
import com.gingersoft.gsa.cloud.database.bean.PrintCurrencyBean; import com.gingersoft.gsa.cloud.database.bean.PrintCurrencyBean;
import com.gingersoft.gsa.cloud.database.bean.PrinterDeviceBean; import com.gingersoft.gsa.cloud.database.bean.PrinterDeviceBean;
import com.gingersoft.gsa.cloud.database.utils.FoodModifierDaoUtils;
import com.gingersoft.gsa.cloud.print.PrintExecutor; import com.gingersoft.gsa.cloud.print.PrintExecutor;
import com.gingersoft.gsa.cloud.print.PrintSocketHolder; import com.gingersoft.gsa.cloud.print.PrintSocketHolder;
import com.gingersoft.gsa.cloud.print.bean.PrintContent; import com.gingersoft.gsa.cloud.print.bean.PrintContent;
import com.gingersoft.gsa.cloud.print.bean.PrjBean; import com.gingersoft.gsa.cloud.print.bean.PrjBean;
import com.jess.arms.base.BaseActivity; import com.jess.arms.base.BaseActivity;
import com.jess.arms.di.component.AppComponent; import com.jess.arms.di.component.AppComponent;
import com.jess.arms.integration.AppManager;
import com.jess.arms.utils.ArmsUtils; import com.jess.arms.utils.ArmsUtils;
import com.joe.print.di.component.DaggerPrintComponent; import com.joe.print.di.component.DaggerPrintComponent;
import com.joe.print.mvp.contract.PrintContract; import com.joe.print.mvp.contract.PrintContract;
...@@ -46,9 +50,16 @@ import com.joe.print.mvp.ui.view.PrinterLoadingDialog; ...@@ -46,9 +50,16 @@ import com.joe.print.mvp.ui.view.PrinterLoadingDialog;
import com.joe.print.mvp.ui.view.SelectPrintDevicePopup; import com.joe.print.mvp.ui.view.SelectPrintDevicePopup;
import com.lxj.xpopup.XPopup; import com.lxj.xpopup.XPopup;
import java.net.ConnectException;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.inject.Inject;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import static com.gingersoft.gsa.cloud.common.constans.PrintConstans.PRINT_BILL; import static com.gingersoft.gsa.cloud.common.constans.PrintConstans.PRINT_BILL;
import static com.gingersoft.gsa.cloud.common.constans.PrintConstans.PRINT_OTHER_CLOSING; import static com.gingersoft.gsa.cloud.common.constans.PrintConstans.PRINT_OTHER_CLOSING;
import static com.gingersoft.gsa.cloud.common.constans.PrintConstans.PRINT_OTHER_ORDER; import static com.gingersoft.gsa.cloud.common.constans.PrintConstans.PRINT_OTHER_ORDER;
...@@ -76,6 +87,10 @@ import static com.jess.arms.utils.Preconditions.checkNotNull; ...@@ -76,6 +87,10 @@ import static com.jess.arms.utils.Preconditions.checkNotNull;
*/ */
public class PrintActivity extends BaseActivity<PrintPresenter> implements PrintContract.View, DialogInterface.OnDismissListener, PrintListener, PrintSocketHolder.OnStateChangedListener, PrintExecutor.OnPrintResultListener { public class PrintActivity extends BaseActivity<PrintPresenter> implements PrintContract.View, DialogInterface.OnDismissListener, PrintListener, PrintSocketHolder.OnStateChangedListener, PrintExecutor.OnPrintResultListener {
@Inject
AppManager mAppManager;
public final static int ADD_PRINT_CODE = 1001;//添加打印機回調 public final static int ADD_PRINT_CODE = 1001;//添加打印機回調
public final static int FINISH = 1003;//關閉頁面 public final static int FINISH = 1003;//關閉頁面
public final static int ADD_PRINT_DEVICE = 1004;//添加打印機 public final static int ADD_PRINT_DEVICE = 1004;//添加打印機
...@@ -104,6 +119,8 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print ...@@ -104,6 +119,8 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
private PrinterLoadingDialog printerLoadingDialog; private PrinterLoadingDialog printerLoadingDialog;
private boolean printerResult;
@Override @Override
public void setupActivityComponent(@NonNull AppComponent appComponent) { public void setupActivityComponent(@NonNull AppComponent appComponent) {
DaggerPrintComponent //如找不到该类,请编译一下项目 DaggerPrintComponent //如找不到该类,请编译一下项目
...@@ -115,6 +132,11 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print ...@@ -115,6 +132,11 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
} }
@Override @Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
}
@Override
public int initView(@Nullable Bundle savedInstanceState) { public int initView(@Nullable Bundle savedInstanceState) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH); | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
...@@ -128,23 +150,7 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print ...@@ -128,23 +150,7 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
// .asLoading("加载中..."); // .asLoading("加载中...");
// loadingPopup.show(); // loadingPopup.show();
printerLoadingDialog = new PrinterLoadingDialog(mContext).build(); actionPrinter();
printerLoadingDialog.show();
callId = CCUtil.getNavigateCallId(this);
//獲取打印類型,根據打印類型生成對應的bitmap
type = CCUtil.getNavigateParam(this, PrintConstans.PRINT_TYPE, PrintConstans.PRINT_TEST);
//獲取打印內容
PrintContent printContent = CCUtil.getNavigateParam(this, PrintConstans.PRINT_CONTENT, null);
//訂單編號
mOrderNo = CCUtil.getNavigateParam(this, PrintConstans.PRINT_ORDER_NO, "");
//根據打印類型獲取對應的執行類
printerInIt = PrinterRoot.getPrinterByType(type, printContent);
if (printerInIt != null) {
printerInIt.setPrintListener(this);
}
//初始化打印配置
initPrintConfig(printContent);
PrinterPlugins.setOnPrinterFlowHandler(new PrinterFlowListener() { PrinterPlugins.setOnPrinterFlowHandler(new PrinterFlowListener() {
...@@ -155,39 +161,86 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print ...@@ -155,39 +161,86 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
@Override @Override
public void connectionSuccess() { public void connectionSuccess() {
printerLoadingDialog.setStep(2, PrinterLoadingDialog.status_success); printerLoadingDialog.setStep(2, PrinterLoadingDialog.status_success, null);
} }
@Override @Override
public void connectionError(Exception e) { public void connectionError(Exception e) {
printerLoadingDialog.setStep(2, PrinterLoadingDialog.status_error); printerLoadingDialog.setStep(2, PrinterLoadingDialog.status_error, e.getMessage());
} }
@Override @Override
public void disconnect() { public void disconnect(Exception e) {
printerLoadingDialog.setStep(4, PrinterLoadingDialog.status_success);
} }
@Override @Override
public void onPrinterDataBefore(int orderType, int printType, String printerData, String printerDeviceInfo) { public void onPrinterDataBefore(int orderType, int printType, String printerData, String printerDeviceInfo) {
printerLoadingDialog.setStep(1, PrinterLoadingDialog.status_default); printerLoadingDialog.setStep(1, PrinterLoadingDialog.status_success, null);
} }
@Override @Override
public void onPrinterBitmapBefore(int orderType, int printType, String directoryName, List<Bitmap> bitmaps) { public void onPrinterBitmapBefore(int orderType, int printType, String directoryName, List<Bitmap> bitmaps) {
printerLoadingDialog.setStep(1, PrinterLoadingDialog.status_success); printerLoadingDialog.setStep(1, PrinterLoadingDialog.status_success, null);
} }
@Override @Override
public void onPrintSuccess() { public void onPrintSuccess() {
printerLoadingDialog.setStep(3, PrinterLoadingDialog.status_success); printerResult = true;
printerLoadingDialog.setStep(3, PrinterLoadingDialog.status_success, null);
} }
@Override @Override
public void onPrintError(Exception e, int errorCode) { public void onPrintError(Exception e, int errorCode) {
printerLoadingDialog.setStep(3, PrinterLoadingDialog.status_error); printerLoadingDialog.setStep(3, PrinterLoadingDialog.status_error, e.getMessage());
}
});
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
actionPrinter();
}
private void actionPrinter() {
showPrintLoadingDialog();
callId = CCUtil.getNavigateCallId(this);
//獲取打印類型,根據打印類型生成對應的bitmap
type = CCUtil.getNavigateParam(this, PrintConstans.PRINT_TYPE, PrintConstans.PRINT_TEST);
//獲取打印內容
PrintContent printContent = CCUtil.getNavigateParam(this, PrintConstans.PRINT_CONTENT, null);
//訂單編號
mOrderNo = CCUtil.getNavigateParam(this, PrintConstans.PRINT_ORDER_NO, "");
//根據打印類型獲取對應的執行類
printerInIt = PrinterRoot.getPrinterByType(type, printContent);
if (printerInIt != null) {
printerInIt.setPrintListener(this);
}
//初始化打印配置
initPrintConfig(printContent);
}
private void showPrintLoadingDialog() {
if (printerLoadingDialog != null) {
printerLoadingDialog = printerLoadingDialog.build();
} else {
printerLoadingDialog = new PrinterLoadingDialog(mContext).build();
}
printerLoadingDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
finish();
if (printerResult) {
CC.sendCCResult(callId, CCResult.success());
} else {
CC.sendCCResult(callId, CCResult.error("print error"));
}
} }
}); });
printerLoadingDialog.show();
} }
/** /**
...@@ -196,6 +249,9 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print ...@@ -196,6 +249,9 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
private PrinterDeviceBean defaultPrint; private PrinterDeviceBean defaultPrint;
private void initPrintConfig(PrintContent printContent) { private void initPrintConfig(PrintContent printContent) {
PrinterPlugins.getOnPrinterFlowHandler().onPrinterDataBefore(type, type, GsonUtils.GsonString(printContent), GsonUtils.GsonString(defaultPrint));
//獲取通用打印配置 //獲取通用打印配置
PrintCurrencyBean printCurrencyBean = getCurrencyConfig(); PrintCurrencyBean printCurrencyBean = getCurrencyConfig();
//獲取打印機列表 //獲取打印機列表
...@@ -209,9 +265,6 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print ...@@ -209,9 +265,6 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
// 如果沒有最近使用的打印機,並且當前餐廳只有一台打印機,就用這一台打印機打印 // 如果沒有最近使用的打印機,並且當前餐廳只有一台打印機,就用這一台打印機打印
defaultPrint = mPresenter.getDefaultPrintInList(printerDeviceBeans, (String) SPUtils.get("defaultPrint", "")); defaultPrint = mPresenter.getDefaultPrintInList(printerDeviceBeans, (String) SPUtils.get("defaultPrint", ""));
} }
//生成餐檯打印的一些信息
PrinterPlugins.getOnPrinterFlowHandler().onPrinterDataBefore(type, type, GsonUtils.GsonString(printContent), GsonUtils.GsonString(defaultPrint));
//如果是打印廚房單 //如果是打印廚房單
if (type == PrintConstans.PRINT_KITCHEN) { if (type == PrintConstans.PRINT_KITCHEN) {
//設置廚房單的信息,並且獲取到這個廚房單的打印位置 //設置廚房單的信息,並且獲取到這個廚房單的打印位置
...@@ -326,6 +379,7 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print ...@@ -326,6 +379,7 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
} }
} else { } else {
//獲取打印圖片 //獲取打印圖片
listMap = printerInIt.getPrintBitmapByCount(mContext, defaultPrint); listMap = printerInIt.getPrintBitmapByCount(mContext, defaultPrint);
if (listMap != null) { if (listMap != null) {
zoomBitmaps = listMap.get(""); zoomBitmaps = listMap.get("");
...@@ -367,13 +421,18 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print ...@@ -367,13 +421,18 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
} }
private void addPrintProgress(String printState) { private void addPrintProgress(String printState) {
runOnUiThread(new Runnable() {
@Override
public void run() {
printerLoadingDialog.setTitle(printState); printerLoadingDialog.setTitle(printState);
} }
});
}
@Override @Override
public boolean dispatchTouchEvent(MotionEvent ev) { public boolean dispatchTouchEvent(MotionEvent ev) {
//doSomeTing,點擊當前頁面任意地方自動關閉 //doSomeTing,點擊當前頁面任意地方自動關閉
killMyself(); finish();
return true; return true;
} }
...@@ -383,18 +442,38 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print ...@@ -383,18 +442,38 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
switch (state) { switch (state) {
case PrintSocketHolder.ERROR_0: case PrintSocketHolder.ERROR_0:
tip = "打印成功"; tip = "打印成功";
PrinterPlugins.getOnPrinterFlowHandler().onPrintSuccess();
break; break;
case PrintSocketHolder.ERROR_6: case PrintSocketHolder.ERROR_6:
tip = "生成打印數據失敗"; tip = "生成打印數據失敗";
break; break;
case PrintSocketHolder.ERROR_7: case PrintSocketHolder.ERROR_7:
tip = "連接打印機失敗"; tip = "連接打印機失敗";
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new ConnectException(tip));
break; break;
case PrintSocketHolder.ERROR_4: case PrintSocketHolder.ERROR_4:
tip = "寫入測試頁面數據失敗"; tip = "寫入數據失敗";
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception(tip), 0);
break; break;
case PrintSocketHolder.ERROR_9: case PrintSocketHolder.ERROR_9:
tip = "ip地址不能為空"; tip = "ip地址不能為空";
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new ConnectException(tip));
break;
case PrintSocketHolder.ERROR_10:
tip = "打印機連接成功,獲取輸入流失敗或者發送數據出現問題";
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception(tip), 0);
break;
case PrintSocketHolder.ERROR_11:
tip = "打印機沒紙了";
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception(tip), 0);
break;
case PrintSocketHolder.ERROR_12:
tip = " 打印機初始化失敗,暫時只有針式打印機有";
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new ConnectException(tip));
break;
case PrintSocketHolder.ERROR_TIMEOUT:
tip = "連接打印機超時";
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new ConnectException(tip));
break; break;
case PrintSocketHolder.STATE_0: case PrintSocketHolder.STATE_0:
break; break;
...@@ -407,7 +486,7 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print ...@@ -407,7 +486,7 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
case PrintSocketHolder.STATE_3: case PrintSocketHolder.STATE_3:
tip = "開始寫入數據"; tip = "開始寫入數據";
break; break;
case PrintSocketHolder.STATE_4: case PrintSocketHolder.STATE_4://关闭输出流
tip = "關閉中"; tip = "關閉中";
killMyself(); killMyself();
break; break;
...@@ -421,6 +500,7 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print ...@@ -421,6 +500,7 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
//缺紙 //缺紙
printFailure("打印機缺紙"); printFailure("打印機缺紙");
tip = "打印機缺紙"; tip = "打印機缺紙";
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception(tip), 0);
break; break;
default: default:
break; break;
...@@ -447,7 +527,6 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print ...@@ -447,7 +527,6 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
} else { } else {
CC.sendCCResult(callId, CCResult.error("print error")); CC.sendCCResult(callId, CCResult.error("print error"));
} }
killMyself();
} }
@Override @Override
...@@ -499,8 +578,10 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print ...@@ -499,8 +578,10 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
@Override @Override
public void killMyself() { public void killMyself() {
if (printerResult) {
finish(); finish();
} }
}
@Override @Override
public void showPrinterList(List<PrinterDeviceBean> deviceBeans) { public void showPrinterList(List<PrinterDeviceBean> deviceBeans) {
......
...@@ -2,22 +2,31 @@ package com.joe.print.mvp.ui.view; ...@@ -2,22 +2,31 @@ package com.joe.print.mvp.ui.view;
import android.animation.ValueAnimator; import android.animation.ValueAnimator;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Looper;
import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import com.airbnb.lottie.LottieAnimationView; import com.airbnb.lottie.LottieAnimationView;
import com.gingersoft.gsa.cloud.pay.pos.hywebpos.constant.HywebActionStatusCode;
import com.gingersoft.gsa.cloud.ui.widget.dialog.BaseRetryDialog; import com.gingersoft.gsa.cloud.ui.widget.dialog.BaseRetryDialog;
import com.joe.print.R; import com.joe.print.R;
import com.qmuiteam.qmui.layout.QMUILinearLayout; import com.qmuiteam.qmui.layout.QMUILinearLayout;
import com.qmuiteam.qmui.util.QMUIDisplayHelper; import com.qmuiteam.qmui.util.QMUIDisplayHelper;
import butterknife.BindDrawable;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
/** /**
* 作者:ELEGANT_BIN * 作者:ELEGANT_BIN
* 版本:1.6.0 * 版本:1.6.0
...@@ -31,14 +40,7 @@ public class PrinterLoadingDialog extends BaseRetryDialog { ...@@ -31,14 +40,7 @@ public class PrinterLoadingDialog extends BaseRetryDialog {
private Context mContext; private Context mContext;
private TextView tv_generate_print_data, tv_connecting, tv_printing, tv_print_result; private TextView tv_generate_print_data, tv_connecting, tv_print_result, tv_error_msg;
// @BindDrawable(R.drawable.print_grey_point)
// Drawable mGreyDrawable;
// @BindDrawable(R.drawable.print_green_point)
// Drawable mGreedDrawable;
// @BindDrawable(R.drawable.print_red_point)
// Drawable mReaDrawable;
public static final byte status_default = 0; public static final byte status_default = 0;
public static final byte status_success = 1; public static final byte status_success = 1;
...@@ -52,10 +54,6 @@ public class PrinterLoadingDialog extends BaseRetryDialog { ...@@ -52,10 +54,6 @@ public class PrinterLoadingDialog extends BaseRetryDialog {
super(context, R.style.MyDialogTheme2); super(context, R.style.MyDialogTheme2);
mContext = context; mContext = context;
mRadius = QMUIDisplayHelper.dp2px(mContext, 8); mRadius = QMUIDisplayHelper.dp2px(mContext, 8);
drawables = new Drawable[3];
drawables[0] = getDrawableByResId(R.drawable.print_grey_point);
drawables[1] = getDrawableByResId(R.drawable.print_green_point);
drawables[2] = getDrawableByResId(R.drawable.print_red_point);
} }
@Override @Override
...@@ -77,7 +75,7 @@ public class PrinterLoadingDialog extends BaseRetryDialog { ...@@ -77,7 +75,7 @@ public class PrinterLoadingDialog extends BaseRetryDialog {
public PrinterLoadingDialog build() { public PrinterLoadingDialog build() {
View contentView = buildViews(); View contentView = buildViews();
int screenWidth = (int) (QMUIDisplayHelper.getScreenWidth(mContext) * 0.9); int screenWidth = (int) (QMUIDisplayHelper.getScreenWidth(mContext) * 0.85);
int screenHeight = (int) (QMUIDisplayHelper.getScreenHeight(mContext) * 0.5); int screenHeight = (int) (QMUIDisplayHelper.getScreenHeight(mContext) * 0.5);
setContentView(contentView, new LinearLayout.LayoutParams(screenWidth, screenHeight)); setContentView(contentView, new LinearLayout.LayoutParams(screenWidth, screenHeight));
return this; return this;
...@@ -89,43 +87,117 @@ public class PrinterLoadingDialog extends BaseRetryDialog { ...@@ -89,43 +87,117 @@ public class PrinterLoadingDialog extends BaseRetryDialog {
LottieAnimationView printLottieView = view.findViewById(R.id.lottieAnimationView); LottieAnimationView printLottieView = view.findViewById(R.id.lottieAnimationView);
tv_generate_print_data = view.findViewById(R.id.tv_generate_print_data); tv_generate_print_data = view.findViewById(R.id.tv_generate_print_data);
tv_connecting = view.findViewById(R.id.tv_connecting); tv_connecting = view.findViewById(R.id.tv_connecting);
tv_printing = view.findViewById(R.id.tv_printing);
tv_print_result = view.findViewById(R.id.tv_print_result); tv_print_result = view.findViewById(R.id.tv_print_result);
tv_error_msg = view.findViewById(R.id.tv_error_msg);
textViews = new TextView[]{tv_generate_print_data, tv_connecting, tv_printing, tv_print_result};
ll_container.setRadiusAndShadow(mRadius, QMUIDisplayHelper.dp2px(mContext, mShadowElevationDp), mShadowAlpha); ll_container.setRadiusAndShadow(mRadius, QMUIDisplayHelper.dp2px(mContext, mShadowElevationDp), mShadowAlpha);
printLottieView.setAnimation(R.raw.printer_loading3); printLottieView.setAnimation(R.raw.printer_loading3);
printLottieView.setRepeatCount(ValueAnimator.INFINITE); printLottieView.loop(true);
// printLottieView.addAnimatorUpdateListener((animation) -> { // printLottieView.addAnimatorUpdateListener((animation) -> {
// // Do something.动画状态监听回调 // // Do something.动画状态监听回调
//
// }); // });
printLottieView.playAnimation();//播放动画 printLottieView.playAnimation();//播放动画
// //progress范围0~1f,设置动画进度
// printLottieView.setProgress(0.5f);
// // 自定义动画时长,此处利用ValueAnimator值动画来实时更新AnimationView的进度来达到控制动画时长。
// ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f).setDuration(500);
// animator.start();//启动动画
return view; return view;
} }
private Drawable[] drawables; public void setStep(int step, int status, String errorMsg) {
private TextView[] textViews; tv_generate_print_data.post(new Runnable() {
@Override
public void setStep(int step, int status) { public void run() {
tv_generate_print_data.post(() -> setCompoundDrawableByStatus(status, textViews[step - 1])); if (!TextUtils.isEmpty(errorMsg)) {
tv_error_msg.setText(errorMsg);
tv_error_msg.setVisibility(View.VISIBLE);
} else {
tv_error_msg.setVisibility(View.GONE);
}
switch (step) {
case 1:
if (status == PrinterLoadingDialog.status_success) {
tv_generate_print_data.setCompoundDrawables(null, getDrawableByResId(R.drawable.print_green_point), null, null);
} else if (status == PrinterLoadingDialog.status_error) {
tv_generate_print_data.setCompoundDrawables(null, getDrawableByResId(R.drawable.print_red_point), null, null);
} else {
tv_generate_print_data.setCompoundDrawables(null, getDrawableByResId(R.drawable.print_grey_point), null, null);
}
break;
case 2:
tv_generate_print_data.setCompoundDrawables(null, getDrawableByResId(R.drawable.print_green_point), null, null);
if (status == PrinterLoadingDialog.status_success) {
tv_connecting.setCompoundDrawables(null, getDrawableByResId(R.drawable.print_green_point), null, null);
} else if (status == PrinterLoadingDialog.status_error) {
tv_connecting.setCompoundDrawables(null, getDrawableByResId(R.drawable.print_red_point), null, null);
} else {
tv_connecting.setCompoundDrawables(null, getDrawableByResId(R.drawable.print_grey_point), null, null);
}
break;
case 3:
if (status == PrinterLoadingDialog.status_success) {
tv_print_result.setCompoundDrawables(null, getDrawableByResId(R.drawable.print_green_point), null, null);
} else if (status == PrinterLoadingDialog.status_error) {
tv_print_result.setCompoundDrawables(null, getDrawableByResId(R.drawable.print_red_point), null, null);
} else {
tv_print_result.setCompoundDrawables(null, getDrawableByResId(R.drawable.print_grey_point), null, null);
}
break;
default:
break;
}
setStatusResult(step, status);
}
});
} }
private void setCompoundDrawableByStatus(int status, TextView textView) { private void setStatusResult(int step, int status) {
textView.setCompoundDrawablesWithIntrinsicBounds(textView.getCompoundDrawables()[0], drawables[status], textView.getCompoundDrawables()[2], textView.getCompoundDrawables()[0]); switch (step) {
case 2:
tv_generate_print_data.setText("生成成功");
if (status == PrinterLoadingDialog.status_success) {
tv_connecting.setText("連接成功");
} else if (status == PrinterLoadingDialog.status_error) {
tv_connecting.setText("連接失敗");
} else {
tv_connecting.setText("連接中");
}
break;
case 3:
if (status == PrinterLoadingDialog.status_success) {
tv_connecting.setText("打印成功");
} else if (status == PrinterLoadingDialog.status_error) {
tv_connecting.setText("打印失敗");
} else {
tv_connecting.setText("打印結果");
}
break;
default:
break;
}
} }
private Drawable getDrawableByResId(int resId) { private Drawable getDrawableByResId(int resId) {
return ContextCompat.getDrawable(mContext, resId); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Drawable drawable = mContext.getDrawable(resId);
drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
return drawable;
}
Drawable drawable = mContext.getResources().getDrawable(resId);
drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
return drawable;
} }
protected int getContentViewLayoutId() { protected int getContentViewLayoutId() {
return R.layout.print_dialog_loading; return R.layout.print_dialog_loading;
} }
private OnClickListener onClickListener;
public void setOnClickListener(OnClickListener onClickListener) {
this.onClickListener = onClickListener;
}
public interface OnClickListener {
// void onItemClick(FoodReason item, int position, int deleteNumber);
}
} }
...@@ -10,8 +10,8 @@ ...@@ -10,8 +10,8 @@
<com.airbnb.lottie.LottieAnimationView <com.airbnb.lottie.LottieAnimationView
android:id="@+id/lottieAnimationView" android:id="@+id/lottieAnimationView"
android:layout_width="@dimen/dp_150" android:layout_width="@dimen/dp_180"
android:layout_height="@dimen/dp_150" android:layout_height="@dimen/dp_180"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
app:lottie_autoPlay="true" app:lottie_autoPlay="true"
app:lottie_loop="true" /> app:lottie_loop="true" />
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
android:id="@+id/tv_generate_print_data" android:id="@+id/tv_generate_print_data"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:drawableTop="@drawable/print_grey_point" android:drawableTop="@drawable/print_green_point"
android:text="生成打印數據" android:text="生成打印數據"
android:textColor="@color/black" android:textColor="@color/black"
android:textSize="@dimen/sp_10" /> android:textSize="@dimen/sp_10" />
...@@ -53,28 +53,23 @@ ...@@ -53,28 +53,23 @@
android:background="@color/black" /> android:background="@color/black" />
<TextView <TextView
android:id="@+id/tv_printing" android:id="@+id/tv_print_result"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:drawableTop="@drawable/print_grey_point" android:drawableTop="@drawable/print_grey_point"
android:text="打印中" android:text="結果"
android:textColor="@color/black" android:textColor="@color/black"
android:textSize="@dimen/sp_10" /> android:textSize="@dimen/sp_10" />
</LinearLayout>
<View
android:layout_width="@dimen/dp_50"
android:layout_height="1px"
android:background="@color/black" />
<TextView <TextView
android:id="@+id/tv_print_result" android:id="@+id/tv_error_msg"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:drawableTop="@drawable/print_grey_point" android:layout_marginTop="@dimen/dp_10"
android:text="結果" android:textColor="@color/red"
android:textColor="@color/black" android:textSize="@dimen/font_small"
android:textSize="@dimen/sp_10" /> android:text="連接打印機超時"/>
</LinearLayout>
</com.qmuiteam.qmui.layout.QMUILinearLayout> </com.qmuiteam.qmui.layout.QMUILinearLayout>
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"v": "5.5.7",
"meta": {
"g": "LottieFiles AE 0.1.20",
"a": "",
"k": "",
"d": "",
"tc": "#FFFFFF"
},
"fr": 60,
"ip": 0,
"op": 70,
"w": 1920,
"h": 1080,
"nm": "Printer1",
"ddd": 0,
"assets": [
{
"id": "image_0",
"w": 971,
"h": 803,
"u": "",
"p": "data:image/png;base64,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",
"e": 1
},
{
"id": "image_1",
"w": 511,
"h": 330,
"u": "",
"p": "data:image/png;base64,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",
"e": 1
},
{
"id": "image_2",
"w": 511,
"h": 260,
"u": "",
"p": "data:image/png;base64,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",
"e": 1
},
{
"id": "comp_0",
"layers": [
{
"ddd": 0,
"ind": 1,
"ty": 4,
"nm": "Layer 2 Outlines",
"sr": 1,
"ks": {
"o": {
"a": 0,
"k": 100,
"ix": 11
},
"r": {
"a": 0,
"k": 0,
"ix": 10
},
"p": {
"a": 0,
"k": [
982.613,
813.599,
0
],
"ix": 2
},
"a": {
"a": 0,
"k": [
27.446,
27.451,
0
],
"ix": 1
},
"s": {
"a": 0,
"k": [
100,
100,
100
],
"ix": 6
}
},
"ao": 0,
"shapes": [
{
"ty": "gr",
"it": [
{
"ind": 0,
"ty": "sh",
"ix": 1,
"ks": {
"a": 0,
"k": {
"i": [
[
0,
-15.021
],
[
-15.021,
0
],
[
0,
15.024
],
[
15.019,
0
]
],
"o": [
[
0,
15.024
],
[
15.019,
0
],
[
0,
-15.021
],
[
-15.021,
0
]
],
"v": [
[
-27.196,
-0.014
],
[
-0.016,
27.201
],
[
27.196,
-0.014
],
[
-0.016,
-27.201
]
],
"c": true
},
"ix": 2
},
"nm": "Path 1",
"mn": "ADBE Vector Shape - Group",
"hd": false
},
{
"ty": "fl",
"c": {
"a": 1,
"k": [
{
"i": {
"x": [
0.667
],
"y": [
1
]
},
"o": {
"x": [
0.333
],
"y": [
0
]
},
"t": 0,
"s": [
0.239215686275,
0.901960784314,
0.713725490196,
1
]
},
{
"i": {
"x": [
0.667
],
"y": [
1
]
},
"o": {
"x": [
0.333
],
"y": [
0
]
},
"t": 30,
"s": [
1,
1,
1,
1
]
},
{
"t": 60,
"s": [
0.239215686917,
0.901960790157,
0.713725507259,
1
]
}
],
"ix": 4
},
"o": {
"a": 0,
"k": 100,
"ix": 5
},
"r": 1,
"bm": 0,
"nm": "Fill 1",
"mn": "ADBE Vector Graphic - Fill",
"hd": false
},
{
"ty": "tr",
"p": {
"a": 0,
"k": [
27.446,
27.451
],
"ix": 2
},
"a": {
"a": 0,
"k": [
0,
0
],
"ix": 1
},
"s": {
"a": 0,
"k": [
100,
100
],
"ix": 3
},
"r": {
"a": 0,
"k": 0,
"ix": 6
},
"o": {
"a": 0,
"k": 100,
"ix": 7
},
"sk": {
"a": 0,
"k": 0,
"ix": 4
},
"sa": {
"a": 0,
"k": 0,
"ix": 5
},
"nm": "Transform"
}
],
"nm": "Group 1",
"np": 2,
"cix": 2,
"bm": 0,
"ix": 1,
"mn": "ADBE Vector Group",
"hd": false
}
],
"ip": 0,
"op": 90,
"st": 0,
"bm": 0
},
{
"ddd": 0,
"ind": 2,
"ty": 4,
"nm": "Layer 3 Outlines",
"sr": 1,
"ks": {
"o": {
"a": 0,
"k": 100,
"ix": 11
},
"r": {
"a": 0,
"k": 0,
"ix": 10
},
"p": {
"a": 0,
"k": [
982.613,
737.809,
0
],
"ix": 2
},
"a": {
"a": 0,
"k": [
27.446,
27.455,
0
],
"ix": 1
},
"s": {
"a": 0,
"k": [
100,
100,
100
],
"ix": 6
}
},
"ao": 0,
"shapes": [
{
"ty": "gr",
"it": [
{
"ind": 0,
"ty": "sh",
"ix": 1,
"ks": {
"a": 0,
"k": {
"i": [
[
0,
-15.037
],
[
-15.021,
0
],
[
0,
15.008
],
[
15.019,
0
]
],
"o": [
[
0,
15.008
],
[
15.019,
0
],
[
0,
-15.037
],
[
-15.021,
0
]
],
"v": [
[
-27.196,
0.013
],
[
-0.016,
27.205
],
[
27.196,
0.013
],
[
-0.016,
-27.205
]
],
"c": true
},
"ix": 2
},
"nm": "Path 1",
"mn": "ADBE Vector Shape - Group",
"hd": false
},
{
"ty": "fl",
"c": {
"a": 1,
"k": [
{
"i": {
"x": [
0.667
],
"y": [
1
]
},
"o": {
"x": [
0.333
],
"y": [
0
]
},
"t": 0,
"s": [
1,
1,
1,
1
]
},
{
"i": {
"x": [
0.667
],
"y": [
1
]
},
"o": {
"x": [
0.333
],
"y": [
0
]
},
"t": 30,
"s": [
0.241020619869,
0.901176571846,
0.712560653687,
1
]
},
{
"t": 60,
"s": [
1,
1,
1,
1
]
}
],
"ix": 4
},
"o": {
"a": 0,
"k": 100,
"ix": 5
},
"r": 1,
"bm": 0,
"nm": "Fill 1",
"mn": "ADBE Vector Graphic - Fill",
"hd": false
},
{
"ty": "tr",
"p": {
"a": 0,
"k": [
27.446,
27.455
],
"ix": 2
},
"a": {
"a": 0,
"k": [
0,
0
],
"ix": 1
},
"s": {
"a": 0,
"k": [
100,
100
],
"ix": 3
},
"r": {
"a": 0,
"k": 0,
"ix": 6
},
"o": {
"a": 0,
"k": 100,
"ix": 7
},
"sk": {
"a": 0,
"k": 0,
"ix": 4
},
"sa": {
"a": 0,
"k": 0,
"ix": 5
},
"nm": "Transform"
}
],
"nm": "Group 1",
"np": 2,
"cix": 2,
"bm": 0,
"ix": 1,
"mn": "ADBE Vector Group",
"hd": false
}
],
"ip": 0,
"op": 90,
"st": 0,
"bm": 0
},
{
"ddd": 0,
"ind": 3,
"ty": 2,
"nm": "MainPRinter",
"refId": "image_0",
"sr": 1,
"ks": {
"o": {
"a": 0,
"k": 100,
"ix": 11
},
"r": {
"a": 0,
"k": 0,
"ix": 10
},
"p": {
"a": 0,
"k": [
561,
529.497,
0
],
"ix": 2
},
"a": {
"a": 0,
"k": [
485.229,
401.141,
0
],
"ix": 1
},
"s": {
"a": 0,
"k": [
100,
100,
100
],
"ix": 6
}
},
"ao": 0,
"ip": 0,
"op": 90,
"st": 0,
"bm": 0
},
{
"ddd": 0,
"ind": 4,
"ty": 2,
"nm": "Layer 5",
"refId": "image_1",
"sr": 1,
"ks": {
"o": {
"a": 0,
"k": 100,
"ix": 11
},
"r": {
"a": 0,
"k": 0,
"ix": 10
},
"p": {
"a": 1,
"k": [
{
"i": {
"x": 0.833,
"y": 0.833
},
"o": {
"x": 0.167,
"y": 0.167
},
"t": 25,
"s": [
560.992,
555.489,
0
],
"to": [
0,
51,
0
],
"ti": [
0,
-51,
0
]
},
{
"t": 55,
"s": [
560.992,
861.489,
0
]
}
],
"ix": 2
},
"a": {
"a": 0,
"k": [
255.107,
164.761,
0
],
"ix": 1
},
"s": {
"a": 0,
"k": [
100,
100,
100
],
"ix": 6
}
},
"ao": 0,
"ef": [
{
"ty": 21,
"nm": "Fill",
"np": 9,
"mn": "ADBE Fill",
"ix": 1,
"en": 1,
"ef": [
{
"ty": 10,
"nm": "Fill Mask",
"mn": "ADBE Fill-0001",
"ix": 1,
"v": {
"a": 0,
"k": 0,
"ix": 1
}
},
{
"ty": 7,
"nm": "All Masks",
"mn": "ADBE Fill-0007",
"ix": 2,
"v": {
"a": 0,
"k": 0,
"ix": 2
}
},
{
"ty": 2,
"nm": "Color",
"mn": "ADBE Fill-0002",
"ix": 3,
"v": {
"a": 0,
"k": [
0.239215686917,
0.901960790157,
0.713725507259,
1
],
"ix": 3
}
},
{
"ty": 7,
"nm": "Invert",
"mn": "ADBE Fill-0006",
"ix": 4,
"v": {
"a": 0,
"k": 0,
"ix": 4
}
},
{
"ty": 0,
"nm": "Horizontal Feather",
"mn": "ADBE Fill-0003",
"ix": 5,
"v": {
"a": 0,
"k": 0,
"ix": 5
}
},
{
"ty": 0,
"nm": "Vertical Feather",
"mn": "ADBE Fill-0004",
"ix": 6,
"v": {
"a": 0,
"k": 0,
"ix": 6
}
},
{
"ty": 0,
"nm": "Opacity",
"mn": "ADBE Fill-0005",
"ix": 7,
"v": {
"a": 0,
"k": 1,
"ix": 7
}
}
]
}
],
"ip": 0,
"op": 90,
"st": 0,
"bm": 0
},
{
"ddd": 0,
"ind": 5,
"ty": 2,
"nm": "Layer 6",
"refId": "image_2",
"sr": 1,
"ks": {
"o": {
"a": 0,
"k": 100,
"ix": 11
},
"r": {
"a": 0,
"k": 0,
"ix": 10
},
"p": {
"a": 1,
"k": [
{
"i": {
"x": 0.667,
"y": 1
},
"o": {
"x": 0.333,
"y": 0
},
"t": 0,
"s": [
560.991,
-72.462,
0
],
"to": [
0,
45.667,
0
],
"ti": [
0,
-45.667,
0
]
},
{
"t": 31,
"s": [
560.991,
201.538,
0
]
}
],
"ix": 2
},
"a": {
"a": 0,
"k": [
255.107,
129.788,
0
],
"ix": 1
},
"s": {
"a": 0,
"k": [
100,
100,
100
],
"ix": 6
}
},
"ao": 0,
"ef": [
{
"ty": 21,
"nm": "Fill",
"np": 9,
"mn": "ADBE Fill",
"ix": 1,
"en": 1,
"ef": [
{
"ty": 10,
"nm": "Fill Mask",
"mn": "ADBE Fill-0001",
"ix": 1,
"v": {
"a": 0,
"k": 0,
"ix": 1
}
},
{
"ty": 7,
"nm": "All Masks",
"mn": "ADBE Fill-0007",
"ix": 2,
"v": {
"a": 0,
"k": 0,
"ix": 2
}
},
{
"ty": 2,
"nm": "Color",
"mn": "ADBE Fill-0002",
"ix": 3,
"v": {
"a": 0,
"k": [
0.239215686917,
0.901960790157,
0.713725507259,
1
],
"ix": 3
}
},
{
"ty": 7,
"nm": "Invert",
"mn": "ADBE Fill-0006",
"ix": 4,
"v": {
"a": 0,
"k": 0,
"ix": 4
}
},
{
"ty": 0,
"nm": "Horizontal Feather",
"mn": "ADBE Fill-0003",
"ix": 5,
"v": {
"a": 0,
"k": 0,
"ix": 5
}
},
{
"ty": 0,
"nm": "Vertical Feather",
"mn": "ADBE Fill-0004",
"ix": 6,
"v": {
"a": 0,
"k": 0,
"ix": 6
}
},
{
"ty": 0,
"nm": "Opacity",
"mn": "ADBE Fill-0005",
"ix": 7,
"v": {
"a": 0,
"k": 1,
"ix": 7
}
}
]
}
],
"ip": 0,
"op": 90,
"st": 0,
"bm": 0
},
{
"ddd": 0,
"ind": 6,
"ty": 2,
"nm": "Layer 4",
"refId": "image_2",
"sr": 1,
"ks": {
"o": {
"a": 0,
"k": 100,
"ix": 11
},
"r": {
"a": 0,
"k": 0,
"ix": 10
},
"p": {
"a": 1,
"k": [
{
"i": {
"x": 0.667,
"y": 1
},
"o": {
"x": 0.333,
"y": 0
},
"t": 0,
"s": [
560.991,
201.538,
0
],
"to": [
0,
48.833,
0
],
"ti": [
0,
-48.833,
0
]
},
{
"t": 31,
"s": [
560.991,
494.538,
0
]
}
],
"ix": 2
},
"a": {
"a": 0,
"k": [
255.107,
129.788,
0
],
"ix": 1
},
"s": {
"a": 0,
"k": [
100,
100,
100
],
"ix": 6
}
},
"ao": 0,
"ef": [
{
"ty": 21,
"nm": "Fill",
"np": 9,
"mn": "ADBE Fill",
"ix": 1,
"en": 1,
"ef": [
{
"ty": 10,
"nm": "Fill Mask",
"mn": "ADBE Fill-0001",
"ix": 1,
"v": {
"a": 0,
"k": 0,
"ix": 1
}
},
{
"ty": 7,
"nm": "All Masks",
"mn": "ADBE Fill-0007",
"ix": 2,
"v": {
"a": 0,
"k": 0,
"ix": 2
}
},
{
"ty": 2,
"nm": "Color",
"mn": "ADBE Fill-0002",
"ix": 3,
"v": {
"a": 0,
"k": [
0.239215686917,
0.901960790157,
0.713725507259,
1
],
"ix": 3
}
},
{
"ty": 7,
"nm": "Invert",
"mn": "ADBE Fill-0006",
"ix": 4,
"v": {
"a": 0,
"k": 0,
"ix": 4
}
},
{
"ty": 0,
"nm": "Horizontal Feather",
"mn": "ADBE Fill-0003",
"ix": 5,
"v": {
"a": 0,
"k": 0,
"ix": 5
}
},
{
"ty": 0,
"nm": "Vertical Feather",
"mn": "ADBE Fill-0004",
"ix": 6,
"v": {
"a": 0,
"k": 0,
"ix": 6
}
},
{
"ty": 0,
"nm": "Opacity",
"mn": "ADBE Fill-0005",
"ix": 7,
"v": {
"a": 0,
"k": 1,
"ix": 7
}
}
]
}
],
"ip": 0,
"op": 90,
"st": 0,
"bm": 0
}
]
}
],
"layers": [
{
"ddd": 0,
"ind": 1,
"ty": 0,
"nm": "5572 [Converted]",
"refId": "comp_0",
"sr": 1,
"ks": {
"o": {
"a": 0,
"k": 100,
"ix": 11
},
"r": {
"a": 0,
"k": 0,
"ix": 10
},
"p": {
"a": 0,
"k": [
960,
540,
0
],
"ix": 2
},
"a": {
"a": 0,
"k": [
561,
561,
0
],
"ix": 1
},
"s": {
"a": 0,
"k": [
100,
100,
100
],
"ix": 6
}
},
"ao": 0,
"w": 1122,
"h": 1122,
"ip": 0,
"op": 90,
"st": 0,
"bm": 0
}
],
"markers": []
}
\ No newline at end of file
...@@ -33,7 +33,10 @@ ...@@ -33,7 +33,10 @@
android:name="design_height_in_dp" android:name="design_height_in_dp"
android:value="640"/> android:value="640"/>
<service <service
android:name="com.gingersoft.gsa.cloud.common.service.GetInfoUpdateService" android:name="com.gingersoft.gsa.cloud.common.service.DataNotificationService"
android:enabled="true" />
<service
android:name="com.gingersoft.gsa.cloud.common.service.DataNotificationService2"
android:enabled="true" /> android:enabled="true" />
</application> </application>
</manifest> </manifest>
...@@ -181,6 +181,11 @@ public class GsaCloudApplication extends BaseApplication { ...@@ -181,6 +181,11 @@ public class GsaCloudApplication extends BaseApplication {
* 初始化美團日誌框架 * 初始化美團日誌框架
*/ */
private void initLogan() { private void initLogan() {
if (BuildConfig.DEBUG) {
LoganConfig.UPLOAD_LOG_URL = "http://192.168.1.131:8080/logan-web/logan/upload.json";
} else {
LoganConfig.UPLOAD_LOG_URL = HttpsConstans.HTTP_ADDRESS_URL_HK + "/logan-web/logan/upload.json";
}
com.dianping.logan.LoganConfig config = new com.dianping.logan.LoganConfig.Builder() com.dianping.logan.LoganConfig config = new com.dianping.logan.LoganConfig.Builder()
.setCachePath(getFilesDir().getAbsolutePath()) .setCachePath(getFilesDir().getAbsolutePath())
.setPath(getExternalFilesDir(null).getAbsolutePath() .setPath(getExternalFilesDir(null).getAbsolutePath()
...@@ -392,9 +397,13 @@ public class GsaCloudApplication extends BaseApplication { ...@@ -392,9 +397,13 @@ public class GsaCloudApplication extends BaseApplication {
} }
@Override @Override
public void disconnect() { public void disconnect(Exception e) {
if (e != null) {
LoganManager.w_printer(TAG, e.getMessage());
} else {
LoganManager.w_printer(TAG, "斷開打印機連接"); LoganManager.w_printer(TAG, "斷開打印機連接");
} }
}
}); });
} }
......
...@@ -15,7 +15,7 @@ public class LoganConfig { ...@@ -15,7 +15,7 @@ public class LoganConfig {
public static final String EncryptIV16 = "0123456789012345"; public static final String EncryptIV16 = "0123456789012345";
public static final String APP_ID = "gingersoft1008611"; public static final String APP_ID = "gingersoft1008611";
// public static final String UPLOAD_LOG_URL = HttpsConstans.HTTP_ADDRESS_URL_HK+ "/logan-web/logan/upload.json"; // public static final String UPLOAD_LOG_URL = HttpsConstans.HTTP_ADDRESS_URL_HK+ "/logan-web/logan/upload.json";
public static final String UPLOAD_LOG_URL = "http://192.168.1.131:8080/logan-web/logan/upload.json"; public static String UPLOAD_LOG_URL = "http://192.168.1.131:8080/logan-web/logan/upload.json";
/** /**
* 日誌保留天數 * 日誌保留天數
......
...@@ -14,5 +14,5 @@ public interface ExternalPrinterConnection { ...@@ -14,5 +14,5 @@ public interface ExternalPrinterConnection {
void connectionError(Exception e); void connectionError(Exception e);
void disconnect(); void disconnect(Exception e);
} }
...@@ -15,18 +15,23 @@ import android.os.Build ...@@ -15,18 +15,23 @@ import android.os.Build
import android.os.IBinder import android.os.IBinder
import android.os.PowerManager import android.os.PowerManager
import android.util.Log import android.util.Log
import android.view.View
import android.widget.RemoteViews import android.widget.RemoteViews
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import com.billy.cc.core.component.CC
import com.billy.cc.core.component.CCResult
import com.gingersoft.gsa.cloud.common.R import com.gingersoft.gsa.cloud.common.R
import com.gingersoft.gsa.cloud.common.constans.AppConstans import com.gingersoft.gsa.cloud.common.constans.AppConstans
import com.gingersoft.gsa.cloud.common.constans.HttpsConstans import com.gingersoft.gsa.cloud.common.constans.HttpsConstans
import com.gingersoft.gsa.cloud.common.constans.PrintConstans
import com.gingersoft.gsa.cloud.common.core.restaurant.RestaurantInfoManager import com.gingersoft.gsa.cloud.common.core.restaurant.RestaurantInfoManager
import com.gingersoft.gsa.cloud.common.core.user.UserContext import com.gingersoft.gsa.cloud.common.core.user.UserContext
import com.gingersoft.gsa.cloud.common.logan.LoganManager import com.gingersoft.gsa.cloud.common.logan.LoganManager
import com.gingersoft.gsa.cloud.common.utils.SoundPoolUtils import com.gingersoft.gsa.cloud.common.utils.SoundPoolUtils
import com.gingersoft.gsa.cloud.common.utils.okhttpUtils.OkHttp3Utils import com.gingersoft.gsa.cloud.common.utils.okhttpUtils.OkHttp3Utils
import com.gingersoft.gsa.cloud.common.utils.time.TimeUtils import com.gingersoft.gsa.cloud.common.utils.time.TimeUtils
import com.gingersoft.gsa.cloud.component.ComponentName
import com.google.gson.Gson import com.google.gson.Gson
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.Observer import io.reactivex.Observer
...@@ -39,7 +44,7 @@ import org.json.JSONObject ...@@ -39,7 +44,7 @@ import org.json.JSONObject
import java.util.* import java.util.*
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
class GetInfoUpdateService : Service() { class DataNotificationService : Service() {
private val TAG = "heart" private val TAG = "heart"
...@@ -61,13 +66,45 @@ class GetInfoUpdateService : Service() { ...@@ -61,13 +66,45 @@ class GetInfoUpdateService : Service() {
private val CHANNEL_ID = "cloud_gsa" private val CHANNEL_ID = "cloud_gsa"
private var isCreate = false
/**
* prj數據
*/
private var PRJ_DATA = 10
/**
* prj數據
*/
private var TABLE_DATA = 11
companion object { companion object {
@kotlin.jvm.JvmField @kotlin.jvm.JvmField
var loginfo = StringBuffer() var loginfo = StringBuffer()
}
val restaurantId by lazy {
RestaurantInfoManager.newInstance().getRestaurantId() @kotlin.jvm.JvmField
var CONNECTION_TYPE = "connection_type"
/**
* 开启外送接单长连
*/
@kotlin.jvm.JvmField
var OPEN_DELIVET_ORDER_CONNECTION = 2
/**
* 开启外送其他数据接收长连(prj,餐台数据)
*/
@kotlin.jvm.JvmField
var OPEN_OTHER_CONNECTION = 1
/**
* 当前连接类型
*/
@kotlin.jvm.JvmField
var mCurrConnectionType = OPEN_OTHER_CONNECTION
} }
override fun onBind(intent: Intent?): IBinder? { override fun onBind(intent: Intent?): IBinder? {
...@@ -88,12 +125,23 @@ class GetInfoUpdateService : Service() { ...@@ -88,12 +125,23 @@ class GetInfoUpdateService : Service() {
} }
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
//获取当前长连类型
mCurrConnectionType = intent!!.getIntExtra(CONNECTION_TYPE, OPEN_DELIVET_ORDER_CONNECTION)
if (mCurrConnectionType == OPEN_DELIVET_ORDER_CONNECTION) {
// 在API11之后构建Notification的方式 // 在API11之后构建Notification的方式
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel() createNotificationChannel()
} else { } else {
startNotification() startNotification()
} }
}
if (isCreate) {
send(mCurrConnectionType)
}
isCreate = true
putTimeLog("啟動服務onStartCommand") putTimeLog("啟動服務onStartCommand")
return super.onStartCommand(intent, flags, startId) return super.onStartCommand(intent, flags, startId)
} }
...@@ -150,6 +198,14 @@ class GetInfoUpdateService : Service() { ...@@ -150,6 +198,14 @@ class GetInfoUpdateService : Service() {
startForeground(123, builder.build()) startForeground(123, builder.build())
} }
fun cleanNotification() {
// val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// notificationManager.cancelAll()
// notificationManager.cancel(123)
// //停止前台服務
// stopForeground(true)
}
inner class MyBind : Binder() { inner class MyBind : Binder() {
lateinit var block: (isShow: Boolean) -> Unit lateinit var block: (isShow: Boolean) -> Unit
var jumpActivity: Class<*>? = null var jumpActivity: Class<*>? = null
...@@ -163,7 +219,7 @@ class GetInfoUpdateService : Service() { ...@@ -163,7 +219,7 @@ class GetInfoUpdateService : Service() {
} }
fun setOnPostCallBack(postCallBack: PostCallBack?) { fun setOnPostCallBack(postCallBack: PostCallBack?) {
this@GetInfoUpdateService.postCallBack = postCallBack this@DataNotificationService.postCallBack = postCallBack
} }
fun execute(block: (isShow: Boolean) -> Unit) { fun execute(block: (isShow: Boolean) -> Unit) {
...@@ -202,10 +258,9 @@ class GetInfoUpdateService : Service() { ...@@ -202,10 +258,9 @@ class GetInfoUpdateService : Service() {
it.newWebSocket(request, object : WebSocketListener() { it.newWebSocket(request, object : WebSocketListener() {
override fun onOpen(webSocket: WebSocket, response: Response) {//开启长连接成功的回调 override fun onOpen(webSocket: WebSocket, response: Response) {//开启长连接成功的回调
super.onOpen(webSocket, response) super.onOpen(webSocket, response)
if (!this@GetInfoUpdateService.isDestroy) { if (!this@DataNotificationService.isDestroy) {
mWebSocket = webSocket mWebSocket = webSocket
val token = "weixin_" + restaurantId + "_" + getRandomString(24) send(mCurrConnectionType)
webSocket.send(Gson().toJson(MsgBean(1, token)))
putTimeLog("連接成功") putTimeLog("連接成功")
cancelTimerDisposable() cancelTimerDisposable()
myBind?.block?.invoke(false) myBind?.block?.invoke(false)
...@@ -232,11 +287,20 @@ class GetInfoUpdateService : Service() { ...@@ -232,11 +287,20 @@ class GetInfoUpdateService : Service() {
// \n5:歷史訂單通知, // \n5:歷史訂單通知,
// \n6:修改訂單狀態通知, // \n6:修改訂單狀態通知,
// \n7:支付成功通知" // \n7:支付成功通知"
// 10:prj数据
// 11:餐台数据
if (type == 3 || type == 4 || type == 5 || type == 7) { if (type == 3 || type == 4 || type == 5 || type == 7) {
//播放提示音 //播放提示音
initSoundPool(R.raw.newordervocal) initSoundPool(R.raw.newordervocal)
} else if (type == 8) { } else if (type == 8) {
initSoundPool(R.raw.raw_logistics_cancel) initSoundPool(R.raw.raw_logistics_cancel)
} else if (type == PRJ_DATA) {
CC.obtainBuilder(ComponentName.COMPONENT_PRINT)
.setActionName("getPrjData")
.build()
.call()
} else if (type == TABLE_DATA) {
} }
//收到服务器端传过来的消息text //收到服务器端传过来的消息text
Log.e(TAG, "onMessage:$text") Log.e(TAG, "onMessage:$text")
...@@ -270,7 +334,8 @@ class GetInfoUpdateService : Service() { ...@@ -270,7 +334,8 @@ class GetInfoUpdateService : Service() {
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {//长连接连接失败的回调 override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {//长连接连接失败的回调
super.onFailure(webSocket, t, response) super.onFailure(webSocket, t, response)
Log.e(TAG, "onFailure " + t.message) Log.e(TAG, "onFailure " + t.message)
if (!this@GetInfoUpdateService.isDestroy) {
if (!this@DataNotificationService.isDestroy) {
//連接斷開,定時五秒,如果未重連,播放提示音 //連接斷開,定時五秒,如果未重連,播放提示音
delayFun({ delayFun({
initSoundPool(R.raw.raw_disconnect) initSoundPool(R.raw.raw_disconnect)
...@@ -283,6 +348,7 @@ class GetInfoUpdateService : Service() { ...@@ -283,6 +348,7 @@ class GetInfoUpdateService : Service() {
webSocket.cancel() webSocket.cancel()
it.dispatcher().cancelAll() it.dispatcher().cancelAll()
} }
} }
}) })
it.dispatcher().executorService().shutdown() it.dispatcher().executorService().shutdown()
...@@ -290,6 +356,21 @@ class GetInfoUpdateService : Service() { ...@@ -290,6 +356,21 @@ class GetInfoUpdateService : Service() {
}, HEART_BEAT_RATE) }, HEART_BEAT_RATE)
} }
fun send(currConnectionType: Int) {
val token = "weixin_" + RestaurantInfoManager.newInstance().restaurantId + "_" + UserContext.newInstance().memberId + "_" + getRandomString(24)
if (mWebSocket != null) {
mWebSocket?.send(Gson().toJson(MsgBean(1, getConnectiontype(), token)))
}
}
private fun getConnectiontype(): String {
var connectiontype = "$OPEN_OTHER_CONNECTION"
if (mCurrConnectionType == OPEN_DELIVET_ORDER_CONNECTION) {
connectiontype = "$OPEN_OTHER_CONNECTION , $OPEN_DELIVET_ORDER_CONNECTION"
}
return connectiontype
}
private var lastSoundTime: Long = 0L private var lastSoundTime: Long = 0L
fun initSoundPool(resId: Int) { fun initSoundPool(resId: Int) {
val nowTime = System.currentTimeMillis()//當前時間減去上次播放的時間,如果超過五秒,那麼才會再次播放提示聲 val nowTime = System.currentTimeMillis()//當前時間減去上次播放的時間,如果超過五秒,那麼才會再次播放提示聲
...@@ -346,7 +427,7 @@ class GetInfoUpdateService : Service() { ...@@ -346,7 +427,7 @@ class GetInfoUpdateService : Service() {
private fun clearHeart() { private fun clearHeart() {
val requestBody = FormBody.Builder() val requestBody = FormBody.Builder()
.add("restaurantId", restaurantId.toString()) .add("restaurantId", RestaurantInfoManager.newInstance().restaurantId .toString())
.build() .build()
OkHttp3Utils.post(HttpsConstans.ROOT_URL + "/member-web/api/restaurant/clearHeartbeat", requestBody) OkHttp3Utils.post(HttpsConstans.ROOT_URL + "/member-web/api/restaurant/clearHeartbeat", requestBody)
.subscribeOn(Schedulers.io()).subscribe() .subscribeOn(Schedulers.io()).subscribe()
...@@ -355,7 +436,10 @@ class GetInfoUpdateService : Service() { ...@@ -355,7 +436,10 @@ class GetInfoUpdateService : Service() {
inner class ClearHeartBroadcastReceiver : BroadcastReceiver() { inner class ClearHeartBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) { override fun onReceive(context: Context?, intent: Intent?) {
//關閉service,會調用service的onDestroy //關閉service,會調用service的onDestroy
stopSelf() // stopSelf()
cleanNotification()
mCurrConnectionType = OPEN_OTHER_CONNECTION;
send(mCurrConnectionType)
} }
} }
...@@ -428,6 +512,6 @@ class GetInfoUpdateService : Service() { ...@@ -428,6 +512,6 @@ class GetInfoUpdateService : Service() {
}) })
} }
class MsgBean(var type: Int, var token: String) class MsgBean(var type: Int, var data: String, var token: String)
} }
\ No newline at end of file
...@@ -182,7 +182,7 @@ public class PrintSocketHolder { ...@@ -182,7 +182,7 @@ public class PrintSocketHolder {
socket = null; socket = null;
error = true; error = true;
} }
PrinterPlugins.getOnPrinterFlowHandler().disconnect(); PrinterPlugins.getOnPrinterFlowHandler().disconnect(null);
return error ? ERROR_66 : ERROR_0; return error ? ERROR_66 : ERROR_0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment