diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index fb7f4a8..b589d56 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 4bc4fc6..17864e8 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,5 +1,4 @@
-
-
+
\ No newline at end of file
diff --git a/app/src/main/java/com/tenlion/xztouch/MainActivity.java b/app/src/main/java/com/tenlion/xztouch/MainActivity.java
index 5f8f2d9..c7776f3 100644
--- a/app/src/main/java/com/tenlion/xztouch/MainActivity.java
+++ b/app/src/main/java/com/tenlion/xztouch/MainActivity.java
@@ -70,6 +70,7 @@ import com.tenlionsoft.baselib.core.widget.marqueen.SimpleMarqueeView;
import com.tenlionsoft.baselib.core.widget.views.BottomSettingPwdView;
import com.tenlionsoft.baselib.core.widget.views.BottomSettingView;
import com.tenlionsoft.baselib.core.widget.views.CenterDialogUpdateView;
+import com.tenlionsoft.baselib.core.widget.views.TopPingView;
import com.tenlionsoft.baselib.core.widget.views.TypeFaceTextView;
import com.tenlionsoft.baselib.utils.AppUtils;
import com.tenlionsoft.baselib.utils.ExceptionHandler;
@@ -162,6 +163,7 @@ public class MainActivity extends Activity {
intentFilter.addAction(PathConfig.ACTION_SHUT_DOWN);
intentFilter.addAction(PathConfig.ACTION_DO_UPDATE_APP);
intentFilter.addAction(PathConfig.ACTION_APP_INSTALL);
+ intentFilter.addAction(PathConfig.ACTION_NOTIFY_CLIENT_STATUS);
registerReceiver(this.mBoradCast, intentFilter);
this.mBaseUrl = SPUtils.getInstance().getString("baseUrl");
this.mDeviceCode = SPUtils.getInstance().getString("deviceCode");
@@ -849,6 +851,11 @@ public class MainActivity extends Activity {
MainActivity.this.mSettingDialog.dismiss();
}
+ @Override
+ public void showPing() {
+ showPingView();
+ }
+
public void shareQQ() {
MainActivity.this.mSettingDialog.dismiss();
Process.killProcess(Process.myPid());
@@ -862,6 +869,18 @@ public class MainActivity extends Activity {
this.mSettingDialog.show();
}
+ /**
+ * 显示ping
+ */
+ private void showPingView() {
+ TopPingView pingView = new TopPingView.DialogBuilder(MainActivity.this)
+ .setIsBackCancelable(false)
+ .setIscancelable(false)
+ .build();
+ pingView.show();
+
+ }
+
/* access modifiers changed from: private */
public void doSubmitDeviceParams(final String str, String str2, final String str3, String str4, String str5,
String str6, String str7) {
@@ -983,7 +1002,7 @@ public class MainActivity extends Activity {
public void checkAppVersion() {
RetrofitManager.getInstance()
.create(BaseApiService.class)
- .doCheckAppVersion(this.mBaseUrl+BaseUrlApi.APP_VERSION_URL)
+ .doCheckAppVersion(this.mBaseUrl + BaseUrlApi.APP_VERSION_URL)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer() {
@@ -1066,6 +1085,12 @@ public class MainActivity extends Activity {
if (!TextUtils.isEmpty(stringExtra)) {
MainActivity.this.installApp(stringExtra);
}
+ } else if (PathConfig.ACTION_NOTIFY_CLIENT_STATUS.equals(action)) {
+ boolean isRunning = intent.getBooleanExtra("isRunning", false);
+ LogUtils.e("是否正在运行"+isRunning);
+ if (mSettingDialog != null && mSettingDialog.isShowing()) {
+ mSettingDialog.setStatus(isRunning);
+ }
}
}
}
@@ -1142,7 +1167,7 @@ public class MainActivity extends Activity {
public void startDownloadApk() {
ToastUtils.show((CharSequence) "开始下载,请在通知栏查看下载进度");
Intent intent = new Intent(this, DownloadService.class);
- intent.putExtra("downloadUrl", this.mBaseUrl+BaseUrlApi.APP_DOWNLOAD_URL);
+ intent.putExtra("downloadUrl", this.mBaseUrl + BaseUrlApi.APP_DOWNLOAD_URL);
startService(intent);
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tenlion/xztouch/push/ServerClient.java b/app/src/main/java/com/tenlion/xztouch/push/ServerClient.java
index e508a16..337bf14 100755
--- a/app/src/main/java/com/tenlion/xztouch/push/ServerClient.java
+++ b/app/src/main/java/com/tenlion/xztouch/push/ServerClient.java
@@ -4,8 +4,10 @@ import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.graphics.Color;
import android.os.Build;
import android.os.IBinder;
@@ -58,6 +60,7 @@ public class ServerClient extends Service {
FileUploadHolder fileUploadHolder = new FileUploadHolder();
private AsyncServer mAsyncServer = new AsyncServer();
private AsyncHttpServer server = new AsyncHttpServer();
+ private PushCastReceiver mReceiver;
public static void start(Context context) {
Intent intent = new Intent(context, ServerClient.class);
@@ -87,6 +90,10 @@ public class ServerClient extends Service {
stopSelf();
}
}
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(PathConfig.ACTION_GET_CLIENT_STATUS);
+ mReceiver = new PushCastReceiver();
+ registerReceiver(mReceiver, filter);
return super.onStartCommand(intent, flags, startId);
}
@@ -136,6 +143,13 @@ public class ServerClient extends Service {
if (mAsyncServer != null) {
mAsyncServer.stop();
}
+ if (mReceiver != null) {
+ unregisterReceiver(mReceiver);
+ }
+ Intent intent = new Intent();
+ intent.setAction(PathConfig.ACTION_NOTIFY_CLIENT_STATUS);
+ intent.putExtra("isRunning", false);
+ sendBroadcast(intent);
}
private void startServer() {
@@ -161,6 +175,7 @@ public class ServerClient extends Service {
LogUtils.e("开始监听");
}
+
private void getAppConfigInfo(AsyncHttpServerRequest asyncHttpServerRequest,
AsyncHttpServerResponse asyncHttpServerResponse) {
try {
@@ -438,4 +453,23 @@ public class ServerClient extends Service {
this.totalSize += param1ArrayOfbyte.length;
}
}
+
+ public class PushCastReceiver extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (PathConfig.ACTION_GET_CLIENT_STATUS.equals(action)) {
+ boolean isRunning = false;
+ if (mAsyncServer != null) {
+ isRunning = mAsyncServer.isRunning();
+ }
+ Intent newIntent = new Intent();
+ newIntent.setAction(PathConfig.ACTION_NOTIFY_CLIENT_STATUS);
+ newIntent.putExtra("isRunning", isRunning);
+ sendBroadcast(newIntent);
+ }
+ }
+ }
+
}
diff --git a/baselib/build.gradle b/baselib/build.gradle
index fa44116..c400e86 100755
--- a/baselib/build.gradle
+++ b/baselib/build.gradle
@@ -89,7 +89,7 @@ dependencies {
api "io.github.razerdp:BasePopup:$rootProject.popup_version"
//选择器
api 'io.github.lucksiege:pictureselector:v2.7.3-rc08'
- api 'me.rosuh:AndroidFilePicker:0.7.0-x'
+ api 'me.rosuh:AndroidFilePicker:0.8.3'
//toast
api 'com.github.getActivity:ToastUtils:9.5'
diff --git a/baselib/src/main/java/com/tenlionsoft/baselib/constant/PathConfig.java b/baselib/src/main/java/com/tenlionsoft/baselib/constant/PathConfig.java
index 600b1d3..bdab1c1 100755
--- a/baselib/src/main/java/com/tenlionsoft/baselib/constant/PathConfig.java
+++ b/baselib/src/main/java/com/tenlionsoft/baselib/constant/PathConfig.java
@@ -141,5 +141,8 @@ public class PathConfig {
public static final String MODULE = "4";
-
+ public static final String ACTION_ASYNC_SERVER_RUNNING = "com.tenlionsoft.xz_touch.service_running";
+ public static final String ACTION_ASYNC_SERVER_STOP = "com.tenlionsoft.xz_touch.service_stop";
+ public static final String ACTION_GET_CLIENT_STATUS = "com.tenlionsoft.xz_touch_service_status";
+ public static final String ACTION_NOTIFY_CLIENT_STATUS = "com.tenlionsoft.xz_touch_service_status";
}
diff --git a/baselib/src/main/java/com/tenlionsoft/baselib/core/widget/views/BottomSettingView.java b/baselib/src/main/java/com/tenlionsoft/baselib/core/widget/views/BottomSettingView.java
index 4c6f111..80770ab 100755
--- a/baselib/src/main/java/com/tenlionsoft/baselib/core/widget/views/BottomSettingView.java
+++ b/baselib/src/main/java/com/tenlionsoft/baselib/core/widget/views/BottomSettingView.java
@@ -3,6 +3,7 @@ package com.tenlionsoft.baselib.core.widget.views;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
+import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.text.TextUtils;
@@ -21,6 +22,9 @@ import androidx.appcompat.widget.SwitchCompat;
import androidx.exifinterface.media.ExifInterface;
import com.tenlionsoft.baselib.R;
+import com.tenlionsoft.baselib.constant.PathConfig;
+import com.tenlionsoft.baselib.utils.AppUtils;
+import com.tenlionsoft.baselib.utils.LogUtils;
import com.tenlionsoft.baselib.utils.NetworkUtils;
import com.tenlionsoft.baselib.utils.SPUtils;
import com.tenlionsoft.baselib.utils.UserLgUtils;
@@ -43,11 +47,13 @@ public class BottomSettingView extends Dialog {
public EditText mEtUrl;
public EditText mEtWidth;
public ImageView mIvImg;
+ public ImageView mIvPing;
private OnChoseListener mListener;
private AppCompatSpinner mSpAppType;
private View view;
public int windowHeight;
public int windowWidth;
+ private ImageView mIvStatus;
public interface OnChoseListener {
void checkUpdate();
@@ -57,6 +63,8 @@ public class BottomSettingView extends Dialog {
void shareWeChart();
void shareWeibo();
+
+ void showPing();
}
private BottomSettingView(Context context2) {
@@ -99,6 +107,9 @@ public class BottomSettingView extends Dialog {
this.mEtWidth = this.view.findViewById(R.id.et_width);
this.mEtHeight = this.view.findViewById(R.id.et_height);
this.mEtResul = this.view.findViewById(R.id.et_resul);
+ mIvStatus = this.view.findViewById(R.id.iv_status);
+ mIvPing = this.view.findViewById(R.id.iv_ping);
+ mIvPing.setOnClickListener(v -> choseType(5));
setCancelable(false);
setCanceledOnTouchOutside(false);
this.mEtDeviceCode = this.view.findViewById(R.id.et_device_code);
@@ -123,6 +134,20 @@ public class BottomSettingView extends Dialog {
window.setBackgroundDrawable(new ColorDrawable());
window.setSoftInputMode(4);
getScreenSize();
+ //获取服务是否在运行
+ getServiceIsRunning();
+ }
+
+ private void getServiceIsRunning() {
+ boolean serviceIsRunning = AppUtils.serviceIsRunning();
+ LogUtils.e("Service is running " + serviceIsRunning);
+ if (serviceIsRunning) {
+ Intent intent = new Intent();
+ intent.setAction(PathConfig.ACTION_GET_CLIENT_STATUS);
+ context.sendBroadcast(intent);
+ } else {
+ setStatus(false);
+ }
}
public /* synthetic */ void lambda$onCreate$1$BottomSettingView(View view2) {
@@ -155,6 +180,14 @@ public class BottomSettingView extends Dialog {
}
}
+ public void setStatus(boolean isRunning) {
+ if (isRunning) {
+ mIvStatus.setBackgroundResource(R.drawable.ic_running_point);
+ } else {
+ mIvStatus.setBackgroundResource(R.drawable.ic_stop_point);
+ }
+ }
+
public void addOnChoseListener(OnChoseListener onChoseListener) {
this.mListener = onChoseListener;
}
@@ -192,6 +225,8 @@ public class BottomSettingView extends Dialog {
onChoseListener.shareQQ();
} else if (i == 4) {
onChoseListener.checkUpdate();
+ } else if (i == 5) {
+ onChoseListener.showPing();
}
}
diff --git a/baselib/src/main/java/com/tenlionsoft/baselib/core/widget/views/PingDialog.java b/baselib/src/main/java/com/tenlionsoft/baselib/core/widget/views/PingDialog.java
new file mode 100644
index 0000000..0b958bc
--- /dev/null
+++ b/baselib/src/main/java/com/tenlionsoft/baselib/core/widget/views/PingDialog.java
@@ -0,0 +1,4 @@
+package com.tenlionsoft.baselib.core.widget.views;
+
+public class PingDialog {
+}
diff --git a/baselib/src/main/java/com/tenlionsoft/baselib/core/widget/views/TopPingView.java b/baselib/src/main/java/com/tenlionsoft/baselib/core/widget/views/TopPingView.java
new file mode 100755
index 0000000..5bdf2fd
--- /dev/null
+++ b/baselib/src/main/java/com/tenlionsoft/baselib/core/widget/views/TopPingView.java
@@ -0,0 +1,269 @@
+package com.tenlionsoft.baselib.core.widget.views;
+
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.graphics.drawable.ColorDrawable;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import androidx.exifinterface.media.ExifInterface;
+
+import com.hjq.toast.ToastUtils;
+import com.tenlionsoft.baselib.R;
+import com.tenlionsoft.baselib.utils.UIUtil;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
+import io.reactivex.rxjava3.annotations.NonNull;
+import io.reactivex.rxjava3.core.Observable;
+import io.reactivex.rxjava3.core.ObservableOnSubscribe;
+import io.reactivex.rxjava3.core.Observer;
+import io.reactivex.rxjava3.disposables.Disposable;
+import io.reactivex.rxjava3.schedulers.Schedulers;
+
+
+/**
+ * 作者 : Adam on 2018/7/23.
+ * 邮箱 : itgaojian@163.com
+ * 描述 : ping
+ */
+public class TopPingView extends Dialog {
+ public String appType;
+ private Context context;
+
+ private OnChoseListener mListener;
+ private TextView mTvInfo;
+ private TextView mTvStart;
+ private TextView mTvCancel;
+ private EditText mEtUrl;
+ private ProgressDialog mDialog;
+
+
+ public interface OnChoseListener {
+ void checkUpdate();
+
+ void shareQQ();
+
+ void shareWeChart();
+
+ void shareWeibo();
+
+ void showPing();
+ }
+
+ private TopPingView(Context context2) {
+ super(context2, R.style.Dialog_ChoseFile);
+ this.appType = ExifInterface.GPS_MEASUREMENT_2D;
+ this.context = context2;
+ }
+
+ /* access modifiers changed from: protected */
+ public void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ View view = LayoutInflater.from(this.context).inflate(R.layout.dialog_top_ping, null);
+ setContentView(view);
+ setCancelable(false);
+ setCanceledOnTouchOutside(false);
+ mTvInfo = view.findViewById(R.id.tv_info);
+ mEtUrl = view.findViewById(R.id.et_ip);
+ mTvStart = view.findViewById(R.id.tv_confirm);
+ mTvCancel = view.findViewById(R.id.tv_cancel);
+ mTvStart.setOnClickListener(v -> {
+ String url = mEtUrl.getText().toString().trim();
+ if (!TextUtils.isEmpty(url)) {
+ ping(url);
+ } else {
+ ToastUtils.show("请输入要ping的网络地址");
+ }
+ });
+ mTvCancel.setOnClickListener(v -> {
+ hideSoftKeyboard(mEtUrl);
+ this.dismiss();
+ });
+ mDialog = UIUtil.initDialog(context, "执行中...");
+ Window window = getWindow();
+ window.setGravity(Gravity.TOP);
+ window.setWindowAnimations(R.style.Dialog_ChoseFile);
+ WindowManager.LayoutParams attributes = window.getAttributes();
+ attributes.width = -1;
+ attributes.height = -2;
+ window.setAttributes(attributes);
+ window.setBackgroundDrawable(new ColorDrawable());
+ window.setSoftInputMode(4);
+
+ }
+
+
+ public void hideSoftKeyboard(View view) {
+ InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
+ if (view != null) {
+ imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
+ }
+ }
+
+ private void showSoftKeyBoardDialog(EditText editText) {
+ if (editText != null) {
+ editText.setFocusable(true);
+ editText.setFocusableInTouchMode(true);
+ editText.requestFocus();
+ ((InputMethodManager) this.context.getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(editText
+ , 0);
+ }
+ }
+
+ public void addOnChoseListener(OnChoseListener onChoseListener) {
+ this.mListener = onChoseListener;
+ }
+
+ public void show() {
+ super.show();
+ getWindow().clearFlags(131080);
+ }
+
+ public void ping(String url) {
+ Observable.create((ObservableOnSubscribe) emitter -> {
+ StringBuilder buffer = new StringBuilder();
+ String result = ""; // 结果集
+ Process ping;
+ try {
+ ping = Runtime.getRuntime().exec(
+ "ping -c 4 " + url);
+ int status = ping.waitFor(); // 状态
+
+ InputStream input = ping.getInputStream();
+ BufferedReader in = new BufferedReader(new InputStreamReader(input));
+
+ String line = ""; // 长度
+ while ((line = in.readLine()) != null) {
+ buffer.append(line).append("\n");
+ }
+ if (status == 0) {
+ result = buffer.toString();
+ } else {
+ result = "网络不通";
+ }
+ emitter.onNext(result);
+ } catch (IOException | InterruptedException e) {
+ e.printStackTrace();
+ emitter.onError(new Throwable("程序错误"));
+
+ }
+ })
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(@NonNull Disposable d) {
+ mTvStart.setEnabled(false);
+ mTvStart.setText("执行中...");
+ mTvInfo.setText("运行中...");
+ }
+
+ @Override
+ public void onNext(@NonNull String result) {
+ mTvInfo.setText(result);
+ mTvStart.setText("执行");
+ mTvStart.setEnabled(true);
+ }
+
+ @Override
+ public void onError(@NonNull Throwable e) {
+ mTvInfo.setText(e.getMessage());
+ mTvStart.setText("执行");
+ mTvStart.setEnabled(true);
+ }
+
+ @Override
+ public void onComplete() {
+ mTvInfo.setText("");
+ mTvStart.setText("执行");
+ mTvStart.setEnabled(true);
+ }
+ });
+ }
+
+
+ private void choseType(int i) {
+ OnChoseListener onChoseListener = this.mListener;
+ if (onChoseListener == null) {
+ return;
+ }
+ if (i == 1) {
+ onChoseListener.shareWeChart();
+ } else if (i == 2) {
+ onChoseListener.shareWeibo();
+ } else if (i == 3) {
+ onChoseListener.shareQQ();
+ } else if (i == 4) {
+ onChoseListener.checkUpdate();
+ } else if (i == 5) {
+ onChoseListener.showPing();
+ }
+ }
+
+ public static class DialogBuilder {
+ private boolean isCancelable;
+ private boolean isCommentImg;
+ private Context mContext;
+ private int mGravity = 80;
+ private boolean mIsBackable;
+ private boolean mIsShow;
+ private boolean mIsShowOther;
+ private OnChoseListener mListener;
+
+ public DialogBuilder(Context context) {
+ this.mContext = context;
+ }
+
+ public DialogBuilder setIscancelable(boolean z) {
+ this.isCancelable = z;
+ return this;
+ }
+
+ public DialogBuilder setIsBackCancelable(boolean z) {
+ this.mIsBackable = z;
+ return this;
+ }
+
+ public DialogBuilder setShowLocation(int i) {
+ this.mGravity = i;
+ return this;
+ }
+
+ public DialogBuilder setIsShowFile(boolean z) {
+ this.mIsShow = z;
+ return this;
+ }
+
+ public DialogBuilder setIsShowOther(boolean z) {
+ this.mIsShowOther = z;
+ return this;
+ }
+
+ public TopPingView build() {
+ return new TopPingView(this.mContext);
+ }
+
+ public DialogBuilder setIsShowPhoto(String str) {
+ if ("0".equals(str)) {
+ this.isCommentImg = false;
+ } else {
+ this.isCommentImg = true;
+ }
+ return this;
+ }
+ }
+}
\ No newline at end of file
diff --git a/baselib/src/main/java/com/tenlionsoft/baselib/utils/AppUtils.java b/baselib/src/main/java/com/tenlionsoft/baselib/utils/AppUtils.java
index 104748c..0a190b2 100755
--- a/baselib/src/main/java/com/tenlionsoft/baselib/utils/AppUtils.java
+++ b/baselib/src/main/java/com/tenlionsoft/baselib/utils/AppUtils.java
@@ -129,7 +129,7 @@ public final class AppUtils {
.getRunningServices(2147483647)
.iterator();
while (iterator.hasNext()) {
- if ("com.tenlionsoft.xzdisplay.push.ServerClient".equals(((ActivityManager.RunningServiceInfo) iterator.next()).service.getClassName()))
+ if ("com.tenlion.xztouch.push.ServerClient".equals(((ActivityManager.RunningServiceInfo) iterator.next()).service.getClassName()))
return true;
}
return false;
diff --git a/baselib/src/main/res/drawable-xhdpi/ic_ping_link.png b/baselib/src/main/res/drawable-xhdpi/ic_ping_link.png
new file mode 100644
index 0000000..f79f516
Binary files /dev/null and b/baselib/src/main/res/drawable-xhdpi/ic_ping_link.png differ
diff --git a/baselib/src/main/res/drawable-xhdpi/ic_running_point.png b/baselib/src/main/res/drawable-xhdpi/ic_running_point.png
new file mode 100644
index 0000000..eb9d60a
Binary files /dev/null and b/baselib/src/main/res/drawable-xhdpi/ic_running_point.png differ
diff --git a/baselib/src/main/res/drawable-xhdpi/ic_stop_point.png b/baselib/src/main/res/drawable-xhdpi/ic_stop_point.png
new file mode 100644
index 0000000..6084c2a
Binary files /dev/null and b/baselib/src/main/res/drawable-xhdpi/ic_stop_point.png differ
diff --git a/baselib/src/main/res/layout/dialog_bottom_setting.xml b/baselib/src/main/res/layout/dialog_bottom_setting.xml
index ee5e209..45845db 100755
--- a/baselib/src/main/res/layout/dialog_bottom_setting.xml
+++ b/baselib/src/main/res/layout/dialog_bottom_setting.xml
@@ -1,6 +1,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file