Commit 7e27ec13 by 宁斌

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

parent d315d8ac
......@@ -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.core.restaurant.RestaurantInfoManager;
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.toast.ToastUtils;
import com.gingersoft.gsa.cloud.ui.utils.AppDialog;
......@@ -220,7 +220,7 @@ public class ColdChainMainActivity extends BaseFragmentActivity<ColdChainMainPre
private void initService() {
//開啟websocket
Intent intent = new Intent(getApplicationContext(), GetInfoUpdateService.class);
Intent intent = new Intent(getApplicationContext(), DataNotificationService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent);
} else {
......@@ -235,13 +235,13 @@ public class ColdChainMainActivity extends BaseFragmentActivity<ColdChainMainPre
registerReceiver(clearHeartBroadcastReceiver, intentFilter);
}
private GetInfoUpdateService.MyBind bind = null;
private DataNotificationService.MyBind bind = null;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
bind = (GetInfoUpdateService.MyBind) service;
bind = (DataNotificationService.MyBind) service;
if (bind != null) {
bind.setOnPostCallBack(type -> {
// -1斷開連接,\n-2:消息傳輸錯誤,\n0:連接消息,\n1:登錄通知,\n2:登出通知,\n3:外賣送單通知,\n4:自取送單通知,\n5:歷史訂單通知,\n6:修改訂單狀態通知,\n7:支付成功通知"
......
......@@ -28,7 +28,7 @@
</intent-filter>
</activity>
<service android:name="com.gingersoft.gsa.cloud.common.service.GetInfoUpdateService" />
<service android:name="com.gingersoft.gsa.cloud.common.service.DataNotificationService" />
<meta-data
android:name="com.gingersoft.gsa.cloud.common.config.globalconfig.GlobalConfiguration"
......
......@@ -7,7 +7,7 @@ import com.billy.cc.core.component.CCResult;
import com.billy.cc.core.component.CCUtil;
import com.billy.cc.core.component.IComponent;
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.mvp.ui.activity.PrjQueryActivity;
import com.gingersoft.gsa.delivery_pick_mode.mvp.ui.activity.SendOrderActivity;
......@@ -52,7 +52,7 @@ public class DeliveryPickComponent implements IComponent {
CC.sendCCResult(cc.getCallId(), CCResult.success());
break;
case "closeHeart":
Intent intent = new Intent(cc.getContext(), GetInfoUpdateService.class);
Intent intent = new Intent(cc.getContext(), DataNotificationService.class);
cc.getContext().stopService(intent);
break;
case "historyActivity":
......
......@@ -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.user.UserContext
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.okhttpUtils.OkHttp3Utils
import com.gingersoft.gsa.cloud.common.utils.other.TextUtil
......@@ -434,8 +434,8 @@ class PageViewModel(private val repository: WeatherRepository) : ViewModel() {
}, {
listener.invoke(getMsgBean(0, "", false))
it.printStackTrace()
GetInfoUpdateService.loginfo.append("錯誤信息111:" + it.message + " LOCALIZEDMESSAGE:" + it.localizedMessage + it.cause)
GetInfoUpdateService.loginfo.append("\n")
DataNotificationService.loginfo.append("錯誤信息111:" + it.message + " LOCALIZEDMESSAGE:" + it.localizedMessage + it.cause)
DataNotificationService.loginfo.append("\n")
})
}
......@@ -575,12 +575,12 @@ class PageViewModel(private val repository: WeatherRepository) : ViewModel() {
//添加PRJ
//單獨包起來,哪怕這接口報錯也不要影響到正常的邏輯
repository.addPrj(dataBean.Order_ID.toString(), restaurantId.toString(), ids.toString())
GetInfoUpdateService.loginfo.append("添加PRJ:orderId:" + dataBean.Order_ID.toString() + "restaurantId:" + restaurantId + "orderDetailsIds:" + ids.toString())
GetInfoUpdateService.loginfo.append("\n")
DataNotificationService.loginfo.append("添加PRJ:orderId:" + dataBean.Order_ID.toString() + "restaurantId:" + restaurantId + "orderDetailsIds:" + ids.toString())
DataNotificationService.loginfo.append("\n")
}, {
it.printStackTrace()
GetInfoUpdateService.loginfo.append("錯誤信息222:" + it.message + " LOCALIZEDMESSAGE:" + it.localizedMessage + it.cause)
GetInfoUpdateService.loginfo.append("\n")
DataNotificationService.loginfo.append("錯誤信息222:" + it.message + " LOCALIZEDMESSAGE:" + it.localizedMessage + it.cause)
DataNotificationService.loginfo.append("\n")
})
}
if (isPrintBill) {
......
......@@ -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.FunctionManagerConstants
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.order.order.BaseOrder
import com.gingersoft.gsa.cloud.ui.utils.AppDialog
......@@ -395,7 +395,7 @@ class DeliveryOrderMainActivity : BaseActivity<IPresenter>(), View.OnClickListen
private fun initWebsocket() {
//開啟websocket
val service = Intent(applicationContext, GetInfoUpdateService::class.java)
val service = Intent(applicationContext, DataNotificationService::class.java)
val notification: NotificationManagerCompat = NotificationManagerCompat.from(this)
if (!notification.areNotificationsEnabled()) {
//未開啟通知權限
......@@ -446,12 +446,12 @@ class DeliveryOrderMainActivity : BaseActivity<IPresenter>(), View.OnClickListen
unbindService(serviceConnection)
}
var bind: GetInfoUpdateService.MyBind? = null
var bind: DataNotificationService.MyBind? = null
var lastRefreshTime: Long = 0
private var serviceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName, service: IBinder) {
bind = service as GetInfoUpdateService.MyBind
bind = service as DataNotificationService.MyBind
bind?.let { it ->
it.setOnPostCallBack(object : PostCallBack {
override fun callBack(type: Int) {
......
......@@ -5,7 +5,7 @@ import android.widget.TextView;
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;
public class LogActivity extends AppCompatActivity {
......@@ -16,13 +16,13 @@ public class LogActivity extends AppCompatActivity {
setContentView(R.layout.activity_log);
loadInfo();
findViewById(R.id.btn_clear_log).setOnClickListener(v -> {
GetInfoUpdateService.loginfo.setLength(0);
DataNotificationService.loginfo.setLength(0);
loadInfo();
});
findViewById(R.id.btn_back).setOnClickListener(v ->finish());
}
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 {
addComponent 'component-delivery-pick'
addComponent 'component-manager'
addComponent 'component-coldchain'
addComponent 'component-supply-chain'
// addComponent 'component-supply-chain'
addComponent 'component-webview'
addComponent 'component-scan'
addComponent 'component-pay'
......
......@@ -4,9 +4,12 @@ import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
import android.text.TextUtils;
import android.util.SparseArray;
......@@ -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.ActivityJumpStrategy;
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.JsonUtils;
import com.gingersoft.gsa.cloud.common.utils.StytemUtils;
......@@ -196,27 +200,15 @@ public class NewMainActivity extends BaseFragmentActivity<NewMainPresenter> impl
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
}
@Override
protected void onResume() {
super.onResume();
initService();
initFuncationData();
if (((int) SPUtils.get("isFormal", 0)) != 0) {
tv_version_name.setText("v_" + DeviceUtils.getVersionName(this) + "\u3000Beta");
} else {
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
......@@ -225,6 +217,28 @@ public class NewMainActivity extends BaseFragmentActivity<NewMainPresenter> impl
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 @@
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name="com.gingersoft.gsa.cloud.app.GsaCloudApplication"
android:allowBackup="true"
......@@ -19,8 +20,10 @@
android:roundIcon="@mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".mvp.ui.activity.PrintAddCurrencyActivity"/>
<activity android:name=".mvp.ui.activity.PrintActivity" />
<activity android:name=".mvp.ui.activity.PrintAddCurrencyActivity" />
<activity
android:name=".mvp.ui.activity.PrintActivity"
android:launchMode="singleTop" />
<activity android:name=".mvp.ui.activity.PrinterAddActivity" />
<activity android:name=".mvp.ui.activity.PrintTestActivity">
<intent-filter>
......
......@@ -6,8 +6,10 @@ import com.billy.cc.core.component.CC;
import com.billy.cc.core.component.CCResult;
import com.billy.cc.core.component.CCUtil;
import com.billy.cc.core.component.IComponent;
import com.gingersoft.gsa.cloud.common.constans.PrintConstans;
import com.gingersoft.gsa.cloud.component.ComponentName;
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.ui.activity.PrintActivity;
import com.joe.print.mvp.ui.activity.PrinterListActivity;
......@@ -64,11 +66,14 @@ public class PrintComponent implements IComponent {
cc.getContext().stopService(new Intent(cc.getContext(), PrjService.class));
CC.sendCCResult(cc.getCallId(), CCResult.success());
break;
case "getPrjData":
PrjPtinterManager.getInstance(cc.getContext()).initUsbPrint();
PrjPtinterManager.getInstance(cc.getContext()).getPrjInfo();
break;
default:
// cc.callAsync(new IComponentCallback() {
// @Override
// public void onResult(CC cc, CCResult result) {
//
// }
// });
//这个逻辑分支上没有调用CC.sendCCResult(...),是一种错误的示例
......
......@@ -294,7 +294,6 @@ public class EpsonPrint implements ReceiveListener {
Log.d("eee", "針式打印機創建數據失敗");
//如果是創建數據失敗,說明這個數據有問題,移除掉
bitmaps.remove(bitmap);
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new Exception("針式打印機添加數據失敗" + ip));
updatePrintState(PrintSocketHolder.ERROR_6);
isPrint = false;
return;
......@@ -315,11 +314,11 @@ public class EpsonPrint implements ReceiveListener {
if (statusInfo.getPaper() == 2) {
//沒紙了
updatePrintState(PrintSocketHolder.ERROR_11);
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new Exception("針式打印機缺紙,打印失敗" + ip));
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception("針式打印機缺紙,打印失敗" + ip),0);
} else {
//紙張狀態異常
updatePrintState(PrintSocketHolder.ERROR_11);
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new Exception("針式打印機紙張異常,請重啟打印機" + ip));
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception("針式打印機紙張異常,請重啟打印機" + ip),0);
}
isPrint = false;
return;
......@@ -331,7 +330,7 @@ public class EpsonPrint implements ReceiveListener {
} catch (Exception e) {
Log.d("eee", "針式打印機打印失敗" + ",任務數:" + bitmaps.size() + e.getMessage());
updatePrintState(PrintSocketHolder.ERROR_10);
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new Exception("針式打印機打印報錯" + ip));
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception("打印機連接成功,發送數據出現問題"),0);
mPrinter.clearCommandBuffer();
disconnectPrinter();
isPrint = false;
......
......@@ -26,4 +26,7 @@ public class PrinterManager {
public void setDeviceBeans(List<PrinterDeviceBean> 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;
import com.gingersoft.gsa.cloud.print.bean.PrintContent;
import com.gingersoft.gsa.cloud.print.bean.PrintTakeawayCheckoutContent;
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.PrintFoodItem;
import com.gingersoft.gsa.cloud.print.bean.base.PrintPayTypeItem;
......@@ -283,7 +284,7 @@ public abstract class PrinterRoot<T extends PrintContent> implements PrintSocket
@Override
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);
}
......@@ -308,7 +309,7 @@ public abstract class PrinterRoot<T extends PrintContent> implements PrintSocket
} else {
//打印失敗
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
if (code == SendResultCode.SEND_SUCCESS) {
printSuccess();
} else if (code == SendResultCode.SEND_FAILED) {
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception("usb打印失敗"), 0);
printFailure("打印失敗");
}
});
......@@ -440,7 +442,6 @@ public abstract class PrinterRoot<T extends PrintContent> implements PrintSocket
@Override
public void onResult(int errorCode) {
Log.e("eee", "打印結果:" + errorCode);
switch (errorCode) {
case PrintSocketHolder.ERROR_0:
PrinterPlugins.getOnPrinterFlowHandler().onPrintSuccess();
......@@ -448,25 +449,31 @@ public abstract class PrinterRoot<T extends PrintContent> implements PrintSocket
return;
case PrintSocketHolder.ERROR_6:
LoganManager.w_printer(TAG, "生成打印數據失敗");
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new Exception("生成打印數據失敗"));
printFailure("生成打印數據失敗");
break;
case PrintSocketHolder.ERROR_7:
LoganManager.w_printer(TAG, "連接打印機失敗");
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new Exception("連接打印機失敗"));
printFailure("連接打印機失敗");
break;
case PrintSocketHolder.ERROR_10:
LoganManager.w_printer(TAG, "連接打印機失敗(写入页面数据失败),Code:" + PrintSocketHolder.ERROR_10);
LoganManager.w_printer(TAG, "打印機連接成功,發送數據出現問題" );
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception("打印機連接成功,發送數據出現問題"), errorCode);
printFailure("打印失敗,錯誤碼:" + errorCode);
break;
case PrintSocketHolder.ERROR_9:
LoganManager.w_printer(TAG, "連接打印機失敗(必要参数不能为空)");
printFailure("連接打印機失敗,沒有ip地址,錯誤碼:" + errorCode);
LoganManager.w_printer(TAG, "IP地址為空");
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new Exception("IP地址為空"));
printFailure("IP地址為空");
break;
case PrintSocketHolder.ERROR_66:
LoganManager.w_printer(TAG, "关闭Socket出错");
LoganManager.w_printer(TAG, "關閉Socket出錯");
PrinterPlugins.getOnPrinterFlowHandler().disconnect(new Exception("關閉打印機連接出错"));
break;
default:
break;
}
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(null, errorCode);
setPrintState(errorCode);
}
......
......@@ -59,6 +59,7 @@ 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;
......@@ -221,7 +222,6 @@ public class PrjService extends Service implements ReceiveListener {
private int totalPrj;
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) {
Map<String, List<PrjBean.DataBean.Bean>> listMap = new HashMap<>();
......@@ -513,10 +513,10 @@ public class PrjService extends Service implements ReceiveListener {
//將打印的圖片保存到手機中
hookPrinterBitmap(bitmapMaps, beans);
EpsonPrint mPrinter = EpsonPrint.getInstance();
boolean initResult = EpsonPrint.getInstance().initializeObject(this, this, errorCode -> updatePrjState(errorCode, getPrintIds(bitmapMaps)));
if (!initResult) {
//初始化打印機失敗
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new ConnectException("初始化針式打印機失敗"));
updatePrjState(UpdateBean.FAIL_EPSON_INIT, getPrintIds(bitmapMaps));
return;
}
......@@ -524,7 +524,7 @@ public class PrjService extends Service implements ReceiveListener {
Log.d("eee", "針式打印機本次PRJ數量:" + bitmapMaps.size());
for (int i = 0; i < bitmapMaps.size(); i++) {
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 {
PrinterPlugins.getOnPrinterFlowHandler().onPrintSuccess();
updatePrjSuccess(key);
} else if (code == SendResultCode.SEND_FAILED) {
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(null, code);
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception("發送打印數據失敗"), code);
updatePrjFailure(key);
}
});
......@@ -679,7 +679,7 @@ public class PrjService extends Service implements ReceiveListener {
@Override
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);
switch (code) {
case 3:
......@@ -742,8 +742,8 @@ public class PrjService extends Service implements ReceiveListener {
updatePrjSuccess(ids);
} else {
//打印失敗
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception(UpdateBean.getStateByCode(i)), i);
updatePrjState(i, ids);
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(null, i);
}
}
......@@ -755,6 +755,7 @@ public class PrjService extends Service implements ReceiveListener {
});
} catch (RemoteException e) {
e.printStackTrace();
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(e, i);
LoganManager.w_printer(TAG, "N5 RemoteException :" + e.getLocalizedMessage());
updatePrjFailure(ids);
}
......@@ -904,7 +905,7 @@ public class PrjService extends Service implements ReceiveListener {
//打印成功
updatePrjSuccess(s);
} else {
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(null, i);
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception("打印失敗"), i);
//打印失敗
updatePrjFailure(s);
}
......
package com.joe.print.mvp.ui.activity;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
......@@ -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.database.bean.PrintCurrencyBean;
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.PrintSocketHolder;
import com.gingersoft.gsa.cloud.print.bean.PrintContent;
import com.gingersoft.gsa.cloud.print.bean.PrjBean;
import com.jess.arms.base.BaseActivity;
import com.jess.arms.di.component.AppComponent;
import com.jess.arms.integration.AppManager;
import com.jess.arms.utils.ArmsUtils;
import com.joe.print.di.component.DaggerPrintComponent;
import com.joe.print.mvp.contract.PrintContract;
......@@ -46,9 +50,16 @@ import com.joe.print.mvp.ui.view.PrinterLoadingDialog;
import com.joe.print.mvp.ui.view.SelectPrintDevicePopup;
import com.lxj.xpopup.XPopup;
import java.net.ConnectException;
import java.util.List;
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_OTHER_CLOSING;
import static com.gingersoft.gsa.cloud.common.constans.PrintConstans.PRINT_OTHER_ORDER;
......@@ -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 {
@Inject
AppManager mAppManager;
public final static int ADD_PRINT_CODE = 1001;//添加打印機回調
public final static int FINISH = 1003;//關閉頁面
public final static int ADD_PRINT_DEVICE = 1004;//添加打印機
......@@ -104,6 +119,8 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
private PrinterLoadingDialog printerLoadingDialog;
private boolean printerResult;
@Override
public void setupActivityComponent(@NonNull AppComponent appComponent) {
DaggerPrintComponent //如找不到该类,请编译一下项目
......@@ -115,6 +132,11 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
}
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
}
@Override
public int initView(@Nullable Bundle savedInstanceState) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
......@@ -128,23 +150,7 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
// .asLoading("加载中...");
// loadingPopup.show();
printerLoadingDialog = new PrinterLoadingDialog(mContext).build();
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);
actionPrinter();
PrinterPlugins.setOnPrinterFlowHandler(new PrinterFlowListener() {
......@@ -155,39 +161,86 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
@Override
public void connectionSuccess() {
printerLoadingDialog.setStep(2, PrinterLoadingDialog.status_success);
printerLoadingDialog.setStep(2, PrinterLoadingDialog.status_success, null);
}
@Override
public void connectionError(Exception e) {
printerLoadingDialog.setStep(2, PrinterLoadingDialog.status_error);
printerLoadingDialog.setStep(2, PrinterLoadingDialog.status_error, e.getMessage());
}
@Override
public void disconnect() {
printerLoadingDialog.setStep(4, PrinterLoadingDialog.status_success);
public void disconnect(Exception e) {
}
@Override
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
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
public void onPrintSuccess() {
printerLoadingDialog.setStep(3, PrinterLoadingDialog.status_success);
printerResult = true;
printerLoadingDialog.setStep(3, PrinterLoadingDialog.status_success, null);
}
@Override
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
private PrinterDeviceBean defaultPrint;
private void initPrintConfig(PrintContent printContent) {
PrinterPlugins.getOnPrinterFlowHandler().onPrinterDataBefore(type, type, GsonUtils.GsonString(printContent), GsonUtils.GsonString(defaultPrint));
//獲取通用打印配置
PrintCurrencyBean printCurrencyBean = getCurrencyConfig();
//獲取打印機列表
......@@ -209,9 +265,6 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
// 如果沒有最近使用的打印機,並且當前餐廳只有一台打印機,就用這一台打印機打印
defaultPrint = mPresenter.getDefaultPrintInList(printerDeviceBeans, (String) SPUtils.get("defaultPrint", ""));
}
//生成餐檯打印的一些信息
PrinterPlugins.getOnPrinterFlowHandler().onPrinterDataBefore(type, type, GsonUtils.GsonString(printContent), GsonUtils.GsonString(defaultPrint));
//如果是打印廚房單
if (type == PrintConstans.PRINT_KITCHEN) {
//設置廚房單的信息,並且獲取到這個廚房單的打印位置
......@@ -326,6 +379,7 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
}
} else {
//獲取打印圖片
listMap = printerInIt.getPrintBitmapByCount(mContext, defaultPrint);
if (listMap != null) {
zoomBitmaps = listMap.get("");
......@@ -367,13 +421,18 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
}
private void addPrintProgress(String printState) {
runOnUiThread(new Runnable() {
@Override
public void run() {
printerLoadingDialog.setTitle(printState);
}
});
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
//doSomeTing,點擊當前頁面任意地方自動關閉
killMyself();
finish();
return true;
}
......@@ -383,18 +442,38 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
switch (state) {
case PrintSocketHolder.ERROR_0:
tip = "打印成功";
PrinterPlugins.getOnPrinterFlowHandler().onPrintSuccess();
break;
case PrintSocketHolder.ERROR_6:
tip = "生成打印數據失敗";
break;
case PrintSocketHolder.ERROR_7:
tip = "連接打印機失敗";
PrinterPlugins.getOnPrinterFlowHandler().connectionError(new ConnectException(tip));
break;
case PrintSocketHolder.ERROR_4:
tip = "寫入測試頁面數據失敗";
tip = "寫入數據失敗";
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception(tip), 0);
break;
case PrintSocketHolder.ERROR_9:
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;
case PrintSocketHolder.STATE_0:
break;
......@@ -407,7 +486,7 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
case PrintSocketHolder.STATE_3:
tip = "開始寫入數據";
break;
case PrintSocketHolder.STATE_4:
case PrintSocketHolder.STATE_4://关闭输出流
tip = "關閉中";
killMyself();
break;
......@@ -421,6 +500,7 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
//缺紙
printFailure("打印機缺紙");
tip = "打印機缺紙";
PrinterPlugins.getOnPrinterFlowHandler().onPrintError(new Exception(tip), 0);
break;
default:
break;
......@@ -447,7 +527,6 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
} else {
CC.sendCCResult(callId, CCResult.error("print error"));
}
killMyself();
}
@Override
......@@ -499,8 +578,10 @@ public class PrintActivity extends BaseActivity<PrintPresenter> implements Print
@Override
public void killMyself() {
if (printerResult) {
finish();
}
}
@Override
public void showPrinterList(List<PrinterDeviceBean> deviceBeans) {
......
......@@ -2,22 +2,31 @@ package com.joe.print.mvp.ui.view;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Looper;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
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.joe.print.R;
import com.qmuiteam.qmui.layout.QMUILinearLayout;
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
* 版本:1.6.0
......@@ -31,14 +40,7 @@ public class PrinterLoadingDialog extends BaseRetryDialog {
private Context mContext;
private TextView tv_generate_print_data, tv_connecting, tv_printing, tv_print_result;
// @BindDrawable(R.drawable.print_grey_point)
// Drawable mGreyDrawable;
// @BindDrawable(R.drawable.print_green_point)
// Drawable mGreedDrawable;
// @BindDrawable(R.drawable.print_red_point)
// Drawable mReaDrawable;
private TextView tv_generate_print_data, tv_connecting, tv_print_result, tv_error_msg;
public static final byte status_default = 0;
public static final byte status_success = 1;
......@@ -52,10 +54,6 @@ public class PrinterLoadingDialog extends BaseRetryDialog {
super(context, R.style.MyDialogTheme2);
mContext = context;
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
......@@ -77,7 +75,7 @@ public class PrinterLoadingDialog extends BaseRetryDialog {
public PrinterLoadingDialog build() {
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);
setContentView(contentView, new LinearLayout.LayoutParams(screenWidth, screenHeight));
return this;
......@@ -89,43 +87,117 @@ public class PrinterLoadingDialog extends BaseRetryDialog {
LottieAnimationView printLottieView = view.findViewById(R.id.lottieAnimationView);
tv_generate_print_data = view.findViewById(R.id.tv_generate_print_data);
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_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);
printLottieView.setAnimation(R.raw.printer_loading3);
printLottieView.setRepeatCount(ValueAnimator.INFINITE);
printLottieView.loop(true);
// printLottieView.addAnimatorUpdateListener((animation) -> {
// // Do something.动画状态监听回调
//
// });
printLottieView.playAnimation();//播放动画
// //progress范围0~1f,设置动画进度
// printLottieView.setProgress(0.5f);
// // 自定义动画时长,此处利用ValueAnimator值动画来实时更新AnimationView的进度来达到控制动画时长。
// ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f).setDuration(500);
// animator.start();//启动动画
return view;
}
private Drawable[] drawables;
private TextView[] textViews;
public void setStep(int step, int status) {
tv_generate_print_data.post(() -> setCompoundDrawableByStatus(status, textViews[step - 1]));
public void setStep(int step, int status, String errorMsg) {
tv_generate_print_data.post(new Runnable() {
@Override
public void run() {
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) {
textView.setCompoundDrawablesWithIntrinsicBounds(textView.getCompoundDrawables()[0], drawables[status], textView.getCompoundDrawables()[2], textView.getCompoundDrawables()[0]);
private void setStatusResult(int step, int status) {
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) {
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() {
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 @@
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/lottieAnimationView"
android:layout_width="@dimen/dp_150"
android:layout_height="@dimen/dp_150"
android:layout_width="@dimen/dp_180"
android:layout_height="@dimen/dp_180"
android:layout_gravity="center_horizontal"
app:lottie_autoPlay="true"
app:lottie_loop="true" />
......@@ -28,7 +28,7 @@
android:id="@+id/tv_generate_print_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="@drawable/print_grey_point"
android:drawableTop="@drawable/print_green_point"
android:text="生成打印數據"
android:textColor="@color/black"
android:textSize="@dimen/sp_10" />
......@@ -53,28 +53,23 @@
android:background="@color/black" />
<TextView
android:id="@+id/tv_printing"
android:id="@+id/tv_print_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="@drawable/print_grey_point"
android:text="打印中"
android:text="結果"
android:textColor="@color/black"
android:textSize="@dimen/sp_10" />
<View
android:layout_width="@dimen/dp_50"
android:layout_height="1px"
android:background="@color/black" />
</LinearLayout>
<TextView
android:id="@+id/tv_print_result"
android:id="@+id/tv_error_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="@drawable/print_grey_point"
android:text="結果"
android:textColor="@color/black"
android:textSize="@dimen/sp_10" />
</LinearLayout>
android:layout_marginTop="@dimen/dp_10"
android:textColor="@color/red"
android:textSize="@dimen/font_small"
android:text="連接打印機超時"/>
</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 @@
android:name="design_height_in_dp"
android:value="640"/>
<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" />
</application>
</manifest>
......@@ -181,6 +181,11 @@ public class GsaCloudApplication extends BaseApplication {
* 初始化美團日誌框架
*/
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()
.setCachePath(getFilesDir().getAbsolutePath())
.setPath(getExternalFilesDir(null).getAbsolutePath()
......@@ -392,9 +397,13 @@ public class GsaCloudApplication extends BaseApplication {
}
@Override
public void disconnect() {
public void disconnect(Exception e) {
if (e != null) {
LoganManager.w_printer(TAG, e.getMessage());
} else {
LoganManager.w_printer(TAG, "斷開打印機連接");
}
}
});
}
......
......@@ -15,7 +15,7 @@ public class LoganConfig {
public static final String EncryptIV16 = "0123456789012345";
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 = "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 {
void connectionError(Exception e);
void disconnect();
void disconnect(Exception e);
}
......@@ -15,18 +15,23 @@ import android.os.Build
import android.os.IBinder
import android.os.PowerManager
import android.util.Log
import android.view.View
import android.widget.RemoteViews
import androidx.annotation.RequiresApi
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.constans.AppConstans
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.user.UserContext
import com.gingersoft.gsa.cloud.common.logan.LoganManager
import com.gingersoft.gsa.cloud.common.utils.SoundPoolUtils
import com.gingersoft.gsa.cloud.common.utils.okhttpUtils.OkHttp3Utils
import com.gingersoft.gsa.cloud.common.utils.time.TimeUtils
import com.gingersoft.gsa.cloud.component.ComponentName
import com.google.gson.Gson
import io.reactivex.Observable
import io.reactivex.Observer
......@@ -39,7 +44,7 @@ import org.json.JSONObject
import java.util.*
import java.util.concurrent.TimeUnit
class GetInfoUpdateService : Service() {
class DataNotificationService : Service() {
private val TAG = "heart"
......@@ -61,13 +66,45 @@ class GetInfoUpdateService : Service() {
private val CHANNEL_ID = "cloud_gsa"
private var isCreate = false
/**
* prj數據
*/
private var PRJ_DATA = 10
/**
* prj數據
*/
private var TABLE_DATA = 11
companion object {
@kotlin.jvm.JvmField
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? {
......@@ -88,12 +125,23 @@ class GetInfoUpdateService : Service() {
}
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的方式
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel()
} else {
startNotification()
}
}
if (isCreate) {
send(mCurrConnectionType)
}
isCreate = true
putTimeLog("啟動服務onStartCommand")
return super.onStartCommand(intent, flags, startId)
}
......@@ -150,6 +198,14 @@ class GetInfoUpdateService : Service() {
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() {
lateinit var block: (isShow: Boolean) -> Unit
var jumpActivity: Class<*>? = null
......@@ -163,7 +219,7 @@ class GetInfoUpdateService : Service() {
}
fun setOnPostCallBack(postCallBack: PostCallBack?) {
this@GetInfoUpdateService.postCallBack = postCallBack
this@DataNotificationService.postCallBack = postCallBack
}
fun execute(block: (isShow: Boolean) -> Unit) {
......@@ -202,10 +258,9 @@ class GetInfoUpdateService : Service() {
it.newWebSocket(request, object : WebSocketListener() {
override fun onOpen(webSocket: WebSocket, response: Response) {//开启长连接成功的回调
super.onOpen(webSocket, response)
if (!this@GetInfoUpdateService.isDestroy) {
if (!this@DataNotificationService.isDestroy) {
mWebSocket = webSocket
val token = "weixin_" + restaurantId + "_" + getRandomString(24)
webSocket.send(Gson().toJson(MsgBean(1, token)))
send(mCurrConnectionType)
putTimeLog("連接成功")
cancelTimerDisposable()
myBind?.block?.invoke(false)
......@@ -232,11 +287,20 @@ class GetInfoUpdateService : Service() {
// \n5:歷史訂單通知,
// \n6:修改訂單狀態通知,
// \n7:支付成功通知"
// 10:prj数据
// 11:餐台数据
if (type == 3 || type == 4 || type == 5 || type == 7) {
//播放提示音
initSoundPool(R.raw.newordervocal)
} else if (type == 8) {
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
Log.e(TAG, "onMessage:$text")
......@@ -270,7 +334,8 @@ class GetInfoUpdateService : Service() {
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {//长连接连接失败的回调
super.onFailure(webSocket, t, response)
Log.e(TAG, "onFailure " + t.message)
if (!this@GetInfoUpdateService.isDestroy) {
if (!this@DataNotificationService.isDestroy) {
//連接斷開,定時五秒,如果未重連,播放提示音
delayFun({
initSoundPool(R.raw.raw_disconnect)
......@@ -283,6 +348,7 @@ class GetInfoUpdateService : Service() {
webSocket.cancel()
it.dispatcher().cancelAll()
}
}
})
it.dispatcher().executorService().shutdown()
......@@ -290,6 +356,21 @@ class GetInfoUpdateService : Service() {
}, 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
fun initSoundPool(resId: Int) {
val nowTime = System.currentTimeMillis()//當前時間減去上次播放的時間,如果超過五秒,那麼才會再次播放提示聲
......@@ -346,7 +427,7 @@ class GetInfoUpdateService : Service() {
private fun clearHeart() {
val requestBody = FormBody.Builder()
.add("restaurantId", restaurantId.toString())
.add("restaurantId", RestaurantInfoManager.newInstance().restaurantId .toString())
.build()
OkHttp3Utils.post(HttpsConstans.ROOT_URL + "/member-web/api/restaurant/clearHeartbeat", requestBody)
.subscribeOn(Schedulers.io()).subscribe()
......@@ -355,7 +436,10 @@ class GetInfoUpdateService : Service() {
inner class ClearHeartBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
//關閉service,會調用service的onDestroy
stopSelf()
// stopSelf()
cleanNotification()
mCurrConnectionType = OPEN_OTHER_CONNECTION;
send(mCurrConnectionType)
}
}
......@@ -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 {
socket = null;
error = true;
}
PrinterPlugins.getOnPrinterFlowHandler().disconnect();
PrinterPlugins.getOnPrinterFlowHandler().disconnect(null);
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