我的Android进阶之旅------>Android实现用Android手机控制PC端的关机和重启的功能(一)PC服务器端
(地址:http://blog.csdn.net/ouyang_peng/article/details/47004617)
我的Android进阶之旅------>Android实现用Android手机控制PC端的关机和重启的功能(二)Android客户端功能展示
(地址:http://blog.csdn.net/ouyang_peng/article/details/47005739)
通过以上两篇文章,我们了解了Android实现用Android手机控制PC端的关机和重启的的大概功能,现在我们来实现Android客户端的代码。
首先来看看整个项目的结构,如下图所示:
第一步:扫描局域网内所有PC,看是否有PC端的服务器在运行并监听30000端口。
此界面的布局文件为:/res/layout/layout_scanip.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <RelativeLayout android:id="@+id/ll" android:layout_width="200dp" android:layout_height="100dp" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:orientation="vertical" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/scaning" /> <ProgressBar android:id="@+id/progressBar" style="?android:attr/progressBarStyleHorizontal" android:layout_width="100dp" android:layout_height="1dp" /> </LinearLayout> </RelativeLayout> </RelativeLayout>
扫描IP的Activity为com.oyp.shutdown.ScanActivity,代码如下:
package com.oyp.shutdown; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.Window; import android.widget.ProgressBar; import android.widget.Toast; public class ScanActivity extends Activity { private MyWifiManager myWifiManager = null; private String serverIP = "", resultIP = ""; private ScanIPThread scanThread = null; private ProgressBar progressBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().requestFeature(Window.FEATURE_NO_TITLE); int height = getWindow().getWindowManager().getDefaultDisplay() .getHeight(); int width = getWindow().getWindowManager().getDefaultDisplay() .getWidth(); setContentView(R.layout.layout_scanip); progressBar = (ProgressBar) findViewById(R.id.progressBar); myWifiManager = new MyWifiManager(ScanActivity.this); scanThread = new ScanIPThread(); scanThread.start(); } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 1000: Toast.makeText(ScanActivity.this, getString(R.string.find), Toast.LENGTH_SHORT).show(); // 找到可连接PC Intent controlIntent = new Intent(ScanActivity.this, ControlActivity.class); // 将可以连接的ip发过去 controlIntent.putExtra("ip", (String) msg.obj); startActivity(controlIntent); finish(); break; case 2000: Toast.makeText(ScanActivity.this, getString(R.string.notFind), Toast.LENGTH_SHORT).show(); // 没有找到可连接PC Intent reScanIntent = new Intent(ScanActivity.this, ReScanActivity.class); startActivity(reScanIntent); finish(); break; default: progressBar.setMax(254); progressBar.setProgress(msg.what); break; } super.handleMessage(msg); } }; // 扫描连接的WiFi所在网段开启了30000端口的C类ip // 例如,wifi的ip是192.168.1.1 则扫描 192.168.1.1-192.168.1.254 class ScanIPThread extends Thread { @Override public void run() { serverIP = myWifiManager.getServerIp(); int t = serverIP.lastIndexOf(".") + 1; resultIP = serverIP.substring(0, t); boolean flag = false; for (int i = 1; i < 255; i++) { try { Socket socket = new Socket(); InetSocketAddress s = new InetSocketAddress(resultIP + i, 30000); socket.connect(s, 50); Message message = new Message(); message.what = 1000; message.obj = resultIP + i; handler.sendMessage(message); flag = true; socket.close(); break; } catch (IOException e) { handler.sendEmptyMessage(i); } } if (!flag) { handler.sendEmptyMessage(2000); } super.run(); } } }
第二步:如果没有扫描到有PC端的服务器在运行并监听30000端口,则重新扫描或者退出。如上述代码中,当msg.what=2000时,重新进行扫描。
此界面的布局文件为:/res/layout/layout_rescan.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" > <Button android:id="@id/btnReScan" style="@style/StyleButton" android:text="@string/rescan" /> <Button android:id="@id/btnClose" style="@style/StyleButtonClose" android:text="@string/close" /> </LinearLayout>
重新扫描IP的Activity为com.oyp.shutdown.ReScanActivity,代码如下:
package com.oyp.shutdown; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.widget.Button; public class ReScanActivity extends Activity implements OnClickListener { private Button btn_rescan, btn_close; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().requestFeature(Window.FEATURE_LEFT_ICON); setContentView(R.layout.layout_rescan); getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, R.drawable.acticon); btn_rescan = (Button) findViewById(R.id.btnReScan); btn_close = (Button) findViewById(R.id.btnClose); btn_rescan.setOnClickListener(this); btn_close.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btnReScan: Intent intent = new Intent(ReScanActivity.this,ScanActivity.class); startActivity(intent); finish(); break; case R.id.btnClose: finish(); break; default: break; } } }
第二步:扫描到了有PC端的服务器在运行并监听30000端口,则控制PC端关机、重启或者取消关机。如上述代码中,当msg.what=1000时,则打开控制PC端界面。
此界面的布局文件为:/res/layout/layout_control.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" > <Button android:id="@id/btnShutdown" style="@style/StyleButton" android:text="@string/shutdown" /> <Button android:id="@id/btnReboot" style="@style/StyleButton" android:text="@string/reboot" /> <Button android:id="@id/btnCancel" style="@style/StyleButton" android:text="@string/cancel" /> <Button android:id="@id/btnClose" style="@style/StyleButtonClose" android:text="@string/close" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginBottom="6.0dip" android:text=" " android:textSize="12.0dip" /> </LinearLayout>
控制PC端的Activity为com.oyp.shutdown.ControlActivity,代码如下:
package com.oyp.shutdown; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.widget.Button; import android.widget.Toast; public class ControlActivity extends Activity implements OnClickListener { private Button btn_shutdown, btn_restart, btn_cancel, btn_close; private Socket clientSocket;// 客户端socket private DataOutputStream dataOutput = null;// 客户端发送数据 private DataInputStream dataInput = null;// 客户端接收数据 private String connIP = ""; private ConnThread connThread = null; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 1: Toast.makeText(ControlActivity.this, (String) msg.obj, Toast.LENGTH_SHORT).show(); break; default: break; } super.handleMessage(msg); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().requestFeature(Window.FEATURE_LEFT_ICON); setContentView(R.layout.layout_control); getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, R.drawable.acticon); btn_shutdown = (Button) findViewById(R.id.btnShutdown); btn_restart = (Button) findViewById(R.id.btnReboot); btn_cancel = (Button) findViewById(R.id.btnCancel); btn_close = (Button) findViewById(R.id.btnClose); Intent intent = getIntent(); connIP = intent.getStringExtra("ip"); btn_shutdown.setOnClickListener(this); btn_restart.setOnClickListener(this); btn_cancel.setOnClickListener(this); btn_close.setOnClickListener(this); } @Override public void onClick(View v) { // 连接服务器 switch (v.getId()) { case R.id.btnShutdown: final String shutdown = "shutdown"; if (connThread != null) { connThread.interrupt(); } connThread = new ConnThread(connIP, 30000, shutdown); connThread.start(); break; case R.id.btnReboot: final String reboot = "reboot"; if (connThread != null) { connThread.interrupt(); } connThread = new ConnThread(connIP, 30000, reboot); connThread.start(); break; case R.id.btnCancel: final String cancel = "cancel"; if (connThread != null) { connThread.interrupt(); } connThread = new ConnThread(connIP, 30000, cancel); connThread.start(); break; case R.id.btnClose: finish(); break; default: break; } } class ConnThread extends Thread { private String ip; private int port; private String content; public ConnThread(String ip, int port, String content) { this.ip = ip; this.port = port; this.content = content; } @Override public void run() { try { clientSocket = new Socket(ip, port); while (true) { dataOutput = new DataOutputStream( clientSocket.getOutputStream()); dataInput = new DataInputStream( clientSocket.getInputStream()); String msg = ""; if ((dataOutput != null) && (!content.equals(""))) { dataOutput.writeUTF(content); } msg = dataInput.readUTF(); if (msg != null && !"".equals(msg)) { Message message = new Message(); message.what = 1; message.obj = msg; handler.sendMessage(message); } } } catch (Exception e) { e.printStackTrace(); } finally { try { if (dataOutput != null) { dataOutput.close(); } if (dataInput != null) { dataInput.close(); } if (clientSocket != null) { clientSocket = null; } } catch (IOException e) { e.printStackTrace(); } } super.run(); } } }
其中MyWifiManager.java代码如下:
package com.oyp.shutdown; import android.content.Context; import android.net.DhcpInfo; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; public class MyWifiManager { private WifiManager wifiManager; private WifiInfo wifiInfo; private DhcpInfo dhcpInfo; public MyWifiManager(Context context){ wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); wifiInfo = wifiManager.getConnectionInfo(); dhcpInfo = wifiManager.getDhcpInfo(); } //得到本机ip public String getLocalIp(){ return FormatString(dhcpInfo.ipAddress); } //得到服务器ip(热点ip) public String getServerIp(){ return FormatString(dhcpInfo.serverAddress); } //转换ip格式为*.*.*.* public String FormatString(int value){ String strValue=""; byte[] ary = intToByteArray(value); for(int i=ary.length-1;i>=0;i--){ strValue+=(ary[i]&0xFF); if(i>0){ strValue+="."; } } return strValue; } public byte[] intToByteArray(int value){ byte[] b=new byte[4]; for(int i=0;i<4;i++){ int offset = (b.length-1-i)*8; b[i]=(byte) ((value>>>offset)&0xFF); } return b; } }
定义控件ID的文件为/res/values/id.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <item type="id" name="btnAirplane">false</item> <item type="id" name="btnShutdown">false</item> <item type="id" name="btnReScan">false</item> <item type="id" name="btnCancel">false</item> <item type="id" name="btnReboot">false</item> <item type="id" name="btnRecovery">false</item> <item type="id" name="btnBootloader">false</item> <item type="id" name="btnClose">false</item> </resources>
/res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">控制PC</string> <string name="shutdown">关机</string> <string name="rescan">重新扫描</string> <string name="reboot">重启</string> <string name="cancel">取消</string> <string name="please_wait">请稍等......</string> <string name="warning">错误</string> <string name="root">无法获得 Root 权限!</string> <string name="close">退出</string> <string name="ok">确定</string> <string name="scaning">正在扫描......</string> <string name="find">找到可连接PC.</string> <string name="notFind">没有找到可连接PC</string> </resources>/res/values/styles.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="StyleButton"> <item name="android:textSize">16.0dip</item> <item name="android:textStyle">bold</item> <item name="android:textColor">#ffffffff</item> <item name="android:layout_gravity">center_horizontal</item> <item name="android:background">@drawable/btn_selector</item> <item name="android:layout_width">wrap_content</item> <item name="android:layout_height">wrap_content</item> <item name="android:layout_marginLeft">30.0dip</item> <item name="android:layout_marginRight">30.0dip</item> <item name="android:layout_marginBottom">8.0dip</item> </style> <style name="StyleButtonClose"> <item name="android:textSize">16.0dip</item> <item name="android:textStyle">bold</item> <item name="android:textColor">#ffffffff</item> <item name="android:layout_gravity">center_horizontal</item> <item name="android:background">@drawable/btn_close_selector</item> <item name="android:layout_width">wrap_content</item> <item name="android:layout_height">wrap_content</item> <item name="android:layout_marginLeft">30.0dip</item> <item name="android:layout_marginRight">30.0dip</item> <item name="android:layout_marginBottom">8.0dip</item> </style> </resources>
项目描述文件:AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.oyp.shutdown" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@drawable/icon" android:label="@string/app_name" > <activity android:name=".ScanActivity" android:theme="@android:style/Theme.Dialog" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".ReScanActivity" android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@android:style/Theme.Dialog" > </activity> <activity android:name=".ControlActivity" android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@android:style/Theme.Dialog" > </activity> </application> </manifest>
代码可以在此处下载:Android实现用Android手机控制PC端的关机和重启的功能 地址:(http://download.csdn.net/detail/qq446282412/8923991)
====================================================================================
作者:欧阳鹏 欢迎转载,与人分享是进步的源泉!
转载请保留原文地址:http://blog.csdn.net/ouyang_peng
====================================================================================