implemented connecting and disconnecting to embedded

This commit is contained in:
strawmanbobi
2025-12-23 13:34:58 +08:00
parent 9e8b017201
commit 230441f04a
10 changed files with 126 additions and 51 deletions

View File

@@ -3,6 +3,7 @@ apply plugin: 'com.android.application'
android { android {
defaultConfig { defaultConfig {
applicationId "net.irext.ircontrol" applicationId "net.irext.ircontrol"
compileSdk 36
targetSdkVersion 36 targetSdkVersion 36
minSdkVersion 26 minSdkVersion 26
versionCode 7 versionCode 7

View File

@@ -1,11 +1,10 @@
package net.irext.ircontrol.ui.fragment; package net.irext.ircontrol.ui.fragment;
import android.content.Context; import android.content.Context;
import android.graphics.Color;
import android.hardware.ConsumerIrManager; import android.hardware.ConsumerIrManager;
import android.os.Bundle; import android.net.InetAddresses;
import android.os.Handler; import android.os.*;
import android.os.Message;
import android.os.Vibrator;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@@ -29,7 +28,6 @@ import java.io.InputStreamReader;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.net.Socket; import java.net.Socket;
import java.net.UnknownHostException;
/** /**
* Filename: ControlFragment.java * Filename: ControlFragment.java
@@ -76,6 +74,11 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
// define the single instance of IRDecode // define the single instance of IRDecode
private IRDecode mIRDecode; private IRDecode mIRDecode;
private CheckBox mCbUseEmitter;
private EditText mEtEmitterIp;
private ImageButton mBtnConnect;
private TextView mTvConnectionStatus;
public ControlFragment() { public ControlFragment() {
} }
@@ -89,44 +92,48 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
mParent = (ControlActivity)getActivity(); mParent = (ControlActivity)getActivity();
View view = inflater.inflate(R.layout.fragment_control, container, false); View view = inflater.inflate(R.layout.fragment_control, container, false);
ImageButton mBtnPower = view.findViewById(R.id.iv_power); ImageButton btnPower = view.findViewById(R.id.iv_power);
ImageButton mBtnBack = view.findViewById(R.id.iv_back); ImageButton btnBack = view.findViewById(R.id.iv_back);
ImageButton mBtnHome = view.findViewById(R.id.iv_home); ImageButton btnHome = view.findViewById(R.id.iv_home);
ImageButton mBtnMenu = view.findViewById(R.id.iv_menu); ImageButton btnMenu = view.findViewById(R.id.iv_menu);
ImageButton mBtnUp = view.findViewById(R.id.iv_up); ImageButton btnUp = view.findViewById(R.id.iv_up);
ImageButton mBtnDown = view.findViewById(R.id.iv_down); ImageButton btnDown = view.findViewById(R.id.iv_down);
ImageButton mBtnLeft = view.findViewById(R.id.iv_left); ImageButton btnLeft = view.findViewById(R.id.iv_left);
ImageButton mBtnRight = view.findViewById(R.id.iv_right); ImageButton btnRight = view.findViewById(R.id.iv_right);
ImageButton mBtnOK = view.findViewById(R.id.iv_ok); ImageButton btnOK = view.findViewById(R.id.iv_ok);
ImageButton mBtnPlus = view.findViewById(R.id.iv_plus); ImageButton btnPlus = view.findViewById(R.id.iv_plus);
ImageButton mBtnMinus = view.findViewById(R.id.iv_minus); ImageButton btnMinus = view.findViewById(R.id.iv_minus);
mBtnPower.setOnClickListener(this); btnPower.setOnClickListener(this);
mBtnBack.setOnClickListener(this); btnBack.setOnClickListener(this);
mBtnHome.setOnClickListener(this); btnHome.setOnClickListener(this);
mBtnMenu.setOnClickListener(this); btnMenu.setOnClickListener(this);
mBtnUp.setOnClickListener(this); btnUp.setOnClickListener(this);
mBtnDown.setOnClickListener(this); btnDown.setOnClickListener(this);
mBtnLeft.setOnClickListener(this); btnLeft.setOnClickListener(this);
mBtnRight.setOnClickListener(this); btnRight.setOnClickListener(this);
mBtnOK.setOnClickListener(this); btnOK.setOnClickListener(this);
mBtnPlus.setOnClickListener(this); btnPlus.setOnClickListener(this);
mBtnMinus.setOnClickListener(this); btnMinus.setOnClickListener(this);
CheckBox mCbUseEmitter = view.findViewById(R.id.cb_use_emitter); mCbUseEmitter = view.findViewById(R.id.cb_use_emitter);
EditText mEtEmitterIp = view.findViewById(R.id.emitter_ip); mEtEmitterIp = view.findViewById(R.id.emitter_ip);
ImageButton mBtnConnect = view.findViewById(R.id.btn_connection_status); mBtnConnect = view.findViewById(R.id.btn_connect_emitter);
mTvConnectionStatus = view.findViewById(R.id.tv_connection_status);
mBtnConnect.setOnClickListener(new View.OnClickListener() { mBtnConnect.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
vibrate(mParent);
String emitterIp = mEtEmitterIp.getText().toString(); String emitterIp = mEtEmitterIp.getText().toString();
if (android.net.InetAddresses.isNumericAddress(emitterIp)) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
connectToEmitter(emitterIp, String.valueOf(EMITTER_PORT)); if (!InetAddresses.isNumericAddress(emitterIp)) {
} else { ToastUtils.showToast(mParent, mParent.getString(R.string.input_emitter_ip_address), null);
ToastUtils.showToast(mParent, mParent.getString(R.string.input_emitter_ip_address), null); return;
}
} }
connectToEmitter(emitterIp, String.valueOf(EMITTER_PORT));
} }
}); });
@@ -232,6 +239,14 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
return mIRDecode.decodeBinary(inputKeyCode, acStatus, 0); return mIRDecode.decodeBinary(inputKeyCode, acStatus, 0);
} }
private void onEmitterConnected() {
emitterConnected = 1;
mParent.runOnUiThread(() -> {
mBtnConnect.setImageDrawable(mParent.getDrawable(R.mipmap.button_unlink));
mTvConnectionStatus.setText(mParent.getString(R.string.status_connected));
mTvConnectionStatus.setTextColor(Color.parseColor("#7F7FFF"));
});
}
private void onEmitterDisconnected() { private void onEmitterDisconnected() {
if (1 == emitterConnected) { if (1 == emitterConnected) {
Log.d(TAG, "emitter disconnected"); Log.d(TAG, "emitter disconnected");
@@ -245,6 +260,9 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
} else { } else {
ToastUtils.showToast(mParent, mParent.getString(R.string.connect_disconnected), Toast.LENGTH_SHORT); ToastUtils.showToast(mParent, mParent.getString(R.string.connect_disconnected), Toast.LENGTH_SHORT);
} }
mBtnConnect.setImageDrawable(mParent.getDrawable(R.mipmap.button_link));
mTvConnectionStatus.setText(mParent.getString(R.string.status_not_connected));
mTvConnectionStatus.setTextColor(Color.parseColor("#FF7F7F"));
}); });
emitterConnected = 0; emitterConnected = 0;
@@ -274,7 +292,7 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
try { try {
emitterConn = new Socket(ipAddress, Integer.parseInt(port)); emitterConn = new Socket(ipAddress, Integer.parseInt(port));
emitterConn.setKeepAlive(true); emitterConn.setKeepAlive(true);
emitterConnected = 1; onEmitterConnected();
BufferedReader in = new BufferedReader(new InputStreamReader(emitterConn.getInputStream())); BufferedReader in = new BufferedReader(new InputStreamReader(emitterConn.getInputStream()));
String line; String line;
while ((line = in.readLine()) != null) { while ((line = in.readLine()) != null) {
@@ -332,7 +350,9 @@ public class ControlFragment extends Fragment implements View.OnClickListener {
decodedValue += ","; decodedValue += ",";
} }
Log.d(TAG, "decodedValue : " + decodedValue); Log.d(TAG, "decodedValue : " + decodedValue);
sendDecodedToEmitter(decodedValue); if (1 == emitterConnected) {
sendDecodedToEmitter(decodedValue);
}
// send decoded integer array to IR emitter // send decoded integer array to IR emitter
ConsumerIrManager irEmitter = ConsumerIrManager irEmitter =
(ConsumerIrManager) mParent.getSystemService(Context.CONSUMER_IR_SERVICE); (ConsumerIrManager) mParent.getSystemService(Context.CONSUMER_IR_SERVICE);

View File

@@ -0,0 +1,16 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<objectAnimator
android:propertyName="translationZ"
android:duration="100"
android:valueTo="0dp"
android:valueType="floatType"/>
</item>
<item>
<objectAnimator
android:propertyName="translationZ"
android:duration="100"
android:valueTo="4dp"
android:valueType="floatType"/>
</item>
</selector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#7f7f7f" />
<corners android:radius="2dp" />
<stroke android:width="4dp" android:color="#FFFFFF" />
</shape>

View File

@@ -26,6 +26,7 @@
android:paddingTop="16dp" android:paddingTop="16dp"
android:paddingBottom="16dp" android:paddingBottom="16dp"
android:contentDescription="@string/button_power" android:contentDescription="@string/button_power"
android:stateListAnimator="@animator/button_elevation_anim"
android:scaleType="fitCenter" android:scaleType="fitCenter"
style="?android:buttonBarButtonStyle"/> style="?android:buttonBarButtonStyle"/>
</LinearLayout> </LinearLayout>
@@ -49,6 +50,7 @@
android:layout_weight="1" android:layout_weight="1"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:contentDescription="@string/button_back" android:contentDescription="@string/button_back"
android:stateListAnimator="@animator/button_elevation_anim"
style="?android:buttonBarButtonStyle"/> style="?android:buttonBarButtonStyle"/>
<ImageButton <ImageButton
android:id="@+id/iv_home" android:id="@+id/iv_home"
@@ -60,6 +62,7 @@
android:layout_weight="1" android:layout_weight="1"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:contentDescription="@string/button_home" android:contentDescription="@string/button_home"
android:stateListAnimator="@animator/button_elevation_anim"
style="?android:buttonBarButtonStyle"/> style="?android:buttonBarButtonStyle"/>
<ImageButton <ImageButton
android:id="@+id/iv_menu" android:id="@+id/iv_menu"
@@ -71,6 +74,7 @@
android:layout_weight="1" android:layout_weight="1"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:contentDescription="@string/button_menu" android:contentDescription="@string/button_menu"
android:stateListAnimator="@animator/button_elevation_anim"
style="?android:buttonBarButtonStyle"/> style="?android:buttonBarButtonStyle"/>
</LinearLayout> </LinearLayout>
@@ -94,6 +98,7 @@
android:layout_weight="1" android:layout_weight="1"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:contentDescription="@string/button_up" android:contentDescription="@string/button_up"
android:stateListAnimator="@animator/button_elevation_anim"
style="?android:buttonBarButtonStyle"/> style="?android:buttonBarButtonStyle"/>
<TextView <TextView
android:id="@+id/tv_empty_top_right" android:id="@+id/tv_empty_top_right"
@@ -117,6 +122,7 @@
android:layout_weight="1" android:layout_weight="1"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:contentDescription="@string/button_left" android:contentDescription="@string/button_left"
android:stateListAnimator="@animator/button_elevation_anim"
style="?android:buttonBarButtonStyle"/> style="?android:buttonBarButtonStyle"/>
<ImageButton <ImageButton
android:id="@+id/iv_ok" android:id="@+id/iv_ok"
@@ -128,6 +134,7 @@
android:layout_weight="1" android:layout_weight="1"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:contentDescription="@string/button_ok" android:contentDescription="@string/button_ok"
android:stateListAnimator="@animator/button_elevation_anim"
style="?android:buttonBarButtonStyle"/> style="?android:buttonBarButtonStyle"/>
<ImageButton <ImageButton
android:id="@+id/iv_right" android:id="@+id/iv_right"
@@ -139,6 +146,7 @@
android:layout_weight="1" android:layout_weight="1"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:contentDescription="@string/button_right" android:contentDescription="@string/button_right"
android:stateListAnimator="@animator/button_elevation_anim"
style="?android:buttonBarButtonStyle"/> style="?android:buttonBarButtonStyle"/>
</LinearLayout> </LinearLayout>
@@ -162,6 +170,7 @@
android:layout_weight="1" android:layout_weight="1"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:contentDescription="@string/button_down" android:contentDescription="@string/button_down"
android:stateListAnimator="@animator/button_elevation_anim"
style="?android:buttonBarButtonStyle"/> style="?android:buttonBarButtonStyle"/>
<TextView <TextView
android:id="@+id/tv_empty_bottom_right" android:id="@+id/tv_empty_bottom_right"
@@ -191,6 +200,7 @@
android:layout_weight="1" android:layout_weight="1"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:contentDescription="@string/button_minus" android:contentDescription="@string/button_minus"
android:stateListAnimator="@animator/button_elevation_anim"
style="?android:buttonBarButtonStyle"/> style="?android:buttonBarButtonStyle"/>
<TextView <TextView
android:id="@+id/tv_empty_center" android:id="@+id/tv_empty_center"
@@ -207,6 +217,7 @@
android:layout_weight="1" android:layout_weight="1"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:contentDescription="@string/button_plus" android:contentDescription="@string/button_plus"
android:stateListAnimator="@animator/button_elevation_anim"
style="?android:buttonBarButtonStyle"/> style="?android:buttonBarButtonStyle"/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
@@ -220,15 +231,30 @@
android:layout_height="1dp" android:layout_height="1dp"
android:layout_margin="4dp" android:layout_margin="4dp"
android:background="#7F7F7F"/> android:background="#7F7F7F"/>
<CheckBox <LinearLayout
android:id="@+id/cb_use_emitter"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="60dp" android:layout_height="wrap_content"
android:textSize="18sp" android:orientation="horizontal">
android:layout_marginStart="20dp" <CheckBox
android:layout_marginEnd="20dp" android:id="@+id/cb_use_emitter"
android:text="@string/use_emitter" android:layout_width="match_parent"
android:checked="false"/> android:layout_height="60dp"
android:textSize="18sp"
android:layout_marginStart="20dp"
android:text="@string/use_emitter"
android:layout_weight="1"
android:checked="false"/>
<TextView
android:id="@+id/tv_connection_status"
android:layout_width="match_parent"
android:layout_height="60dp"
android:gravity="center_vertical|end"
android:layout_marginEnd="20dp"
android:layout_weight="1"
android:textSize="18sp"
android:textColor="#FF7F7F"
android:text="@string/status_not_connected"/>
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -253,18 +279,20 @@
android:autofillHints="" android:autofillHints=""
android:gravity="center_vertical" android:gravity="center_vertical"
android:textSize="18sp" android:textSize="18sp"
android:hint="@string/default_ip"
android:inputType="text" android:inputType="text"
android:text="@string/default_ip"
android:layout_height="60dp" android:layout_height="60dp"
android:layout_weight="1"> android:layout_weight="1">
</EditText> </EditText>
<ImageButton <ImageButton
android:id="@+id/btn_connection_status" android:id="@+id/btn_connect_emitter"
android:layout_width="60dp" android:layout_width="60dp"
android:layout_height="60dp" android:layout_height="60dp"
android:src="@mipmap/connect_emitter" android:padding="12dp"
android:src="@mipmap/button_link"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:contentDescription="@string/connect" android:contentDescription="@string/connect"
android:stateListAnimator="@animator/button_elevation_anim"
style="?android:buttonBarButtonStyle"/> style="?android:buttonBarButtonStyle"/>
</LinearLayout> </LinearLayout>
<View <View

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -33,10 +33,12 @@
<string name="ir_not_supported">该设备不支持红外发射, 请连接外部模块进行发射</string> <string name="ir_not_supported">该设备不支持红外发射, 请连接外部模块进行发射</string>
<string name="emitter_ip">发射端 IP</string> <string name="emitter_ip">发射端 IP</string>
<string name="default_ip">192.168.1.100</string> <string name="default_ip">192.168.2.85</string>
<string name="connect">连接</string> <string name="connect">连接</string>
<string name="use_emitter">使用发射器</string> <string name="use_emitter">使用发射器</string>
<string name="input_emitter_ip_address">请输入接收器的 IP 地址</string> <string name="input_emitter_ip_address">请输入接收器的 IP 地址</string>
<string name="connect_failed">连接失败</string> <string name="connect_failed">连接失败</string>
<string name="connect_disconnected">断开连接</string> <string name="connect_disconnected">连接已断开</string>
<string name="status_not_connected">未连接</string>
<string name="status_connected">已连接</string>
</resources> </resources>

View File

@@ -33,11 +33,13 @@
<string name="ir_not_supported">IR emitter is not supported in this device, please try with external emitters</string> <string name="ir_not_supported">IR emitter is not supported in this device, please try with external emitters</string>
<string name="emitter_ip">Emitter IP</string> <string name="emitter_ip">Emitter IP</string>
<string name="default_ip">192.168.1.100</string> <string name="default_ip">192.168.2.85</string>
<string name="connect">connect</string> <string name="connect">connect</string>
<string name="use_emitter">Use Emitter</string> <string name="use_emitter">Use Emitter</string>
<string name="input_emitter_ip_address">Please input IP address of emitter</string> <string name="input_emitter_ip_address">Please input IP address of emitter</string>
<string name="connect_failed">Connect failed</string> <string name="connect_failed">Connect failed</string>
<string name="connect_disconnected">Disconnected</string> <string name="connect_disconnected">The connection has lost</string>
<string name="status_not_connected">Disconnected</string>
<string name="status_connected">Connected</string>
</resources> </resources>