源碼:點此下載
不知道大家有沒有和我一樣的習慣,喜歡躺在床上看電影,手里還拿着手機玩。。。
所以我就想到了這樣一個程序:用android手機控制電腦上的暴風影音播放(當然,同樣的方法也適用於pps什么的)。大冷天的,來電話需要暫停電影電視的播放,只要在被窩里輕輕一晃手機,就停止播放了,感覺還是挺爽的,哈哈。
首先講一下手機和電腦的互聯:
1,家里有無線網路由器的話,直接將手機介入無線網就可以了。
2,只有手機和筆記本的話,可以打開android的wifi熱點。設置-無線和網絡-綁定與便攜式熱點,打開便攜式熱點。然后用筆記本連接。這里要注意一下,筆記本自動獲取ip的話,就可以通過android上網了,想阻止筆記本聯網(省流量),可以看下筆記本自動獲取到的ip和掩碼,然后將ip改為手動設置,填入剛才自動獲取的ip和掩碼,注意千萬不要設置網關和dns,不然你就等着流量耗完淚奔吧。
下面是實現原理:
播放器都有自己的快捷鍵,比如暴風:空格鍵是暫停,ctrl+left是快退,ctrl+right是快進。所以我就想到了用PostMessage方法向(本來是用SendMessage的,可是不管用,后來改成PostMessage后就好了--//)暴風影音窗口發送鍵盤消息。所以要在電腦上用C#寫一個程序,用來接收android手機的消息,然后使用PostMessage方法來控制暴風影音。無論暴風影音最小化還是全屏播放都是可以接收到消息的。
下面是實現方法:
一,首先是電腦上的C#監聽程序,首先新建一個SendMsg類,實現向暴風影音發送消息。
其中向鍵盤發送的消息,我使用了spy++來不作的,不知道使用的google一下。其中碰到了一個問題,無法使用postMessage向進程發送“Ctrl+left”組合鍵,網上查了一下也說不可以,希望知道的朋友寫一下方法。所以我就在暴風影音里修改了一下快捷鍵,將快進和快退功能分別變為right和left。
實現播放暫停的代碼片段:
/// <summary>
/// 開始,暫停
/// </summary>
public void StartOrStop()
{
PostMessage(mainWindowHander, 0x0100, 0x20, 0x20390001);
PostMessage(mainWindowHander, 0x0101, 0x20, 0x20390001);
}
PostMessage中0x20390001代表空格鍵。PostMessage發動鍵盤消息的使用可以參考C#中使用 SendMessage 向非頂端窗體發送組合鍵。
上面的這個方法模擬在暴風影音上按下,松開空格鍵。
下面是控制暴風影音的代碼:
1 using System;
2 using System.Runtime.InteropServices;
3 using System.Diagnostics;
4 using System.Threading;
5
6 namespace 暴風control
7 {
8 public class SendMsg
9 {
10 [DllImport("user32.dll", EntryPoint = "PostMessage")] //使用系統的非托管代碼。
11 public static extern int PostMessage(
12 IntPtr hwnd,
13 int wMsg,
14 uint wParam,
15 uint lParam
16 );
17
18 IntPtr mainWindowHander;
19
20 /// <summary>
21 /// 遍歷電腦所有的進程,獲取暴風影音句柄
22 /// </summary>
23 public SendMsg()
24 {
25 Process[] allProcesses = Process.GetProcesses();
26 foreach (Process p in allProcesses)
27 {
28 if (p.ProcessName == "StormPlayer") //最新版暴風的進程名是StormPlayer,以前的是Storm在任務管理器里可以看到,這里不一樣要修改一下。
29 mainWindowHander = p.MainWindowHandle;
30 }
31 if (mainWindowHander == IntPtr.Zero)
32 {
33 Process p = new Process();
34 p.StartInfo.FileName = @"D:\Baofeng\StormPlayer\StormPlayer.exe"; //暴風影音地址,改成你們自己的。
35 p.Start();
36 Thread.Sleep(3000); //這里是笨方法,要等待3秒,以免暴風影音進程還沒有啟動就獲取句柄。
37 mainWindowHander = p.MainWindowHandle;
38 }
39 }
40
41 /// <summary>
42 /// 開始,暫停
43 /// </summary>
44 public void StartOrStop()
45 {
46 PostMessage(mainWindowHander, 0x0100, 0x20, 0x20390001);
47 PostMessage(mainWindowHander, 0x0101, 0x20, 0x20390001);
48 }
49
50 /// <summary>
51 /// 快退
52 /// </summary>
53 public void Back()
54 {
55 PostMessage(mainWindowHander, 0x0100, 0x25, 0x204b0001);
56 PostMessage(mainWindowHander, 0x0101, 0x25, 0x204b0001);
57 }
58
59 /// <summary>
60 /// 快進
61 /// </summary>
62 public void Qian()
63 {
64 PostMessage(mainWindowHander, 0x0100, 0x27, 0x204d0001);
65 PostMessage(mainWindowHander, 0x0101, 0x27, 0x204d0001);
66 }
67 }
68 }
二,C#和android使用socket通信。
C#服務端的代碼:
using System;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Windows.Forms;
namespace 暴風control
{
class NetControl
{
SendMsg sendMsg = new SendMsg();
TextBox textBox;
public NetControl(TextBox tmpTextBox)
{
textBox = tmpTextBox;
}
public void BeginListen()
{
Thread.CurrentThread.IsBackground = true;
TcpListener server = new TcpListener(IPAddress.Any, 12121);
server.Start();
while (true)
{
TcpClient client= server.AcceptTcpClient();
Thread clientThread = new Thread(new ParameterizedThreadStart(receiveMsg));
clientThread.Start(client);
}
}
/// <summary>
/// 服務器偵聽
/// </summary>
/// <param name="result"></param>
private void receiveMsg(Object obj)
{
Control.CheckForIllegalCrossThreadCalls = false;
Thread.CurrentThread.IsBackground = true;
using (TcpClient client =(TcpClient)obj)
{
using (NetworkStream stream = client.GetStream())
{
int dataLength = 0;
string str;
string msg;
do
{
byte[] buffer = new byte[32];
dataLength = stream.Read(buffer, 0, buffer.Length);
str = Encoding.ASCII.GetString(buffer, 0, dataLength);
msg = Encoding.ASCII.GetString(buffer);
sendMessage(msg);
textBox.Text += "\r\n" + msg + "\r\n-----";
} while (client.Connected && msg.Substring(0, 4)!="over"); //就受到over字符串就斷開連接,否則會出現死循環。。。
}
}
}
/// <summary>
/// 根據收到信息,使用不同的功能(快進,暫停等)
/// </summary>
private void sendMessage(string msg)
{
string res=msg.Substring(0,4);
switch (res)
{
case "back":
sendMsg.Back();
break;
case "qian":
sendMsg.Qian();
break;
case "stsp":
sendMsg.StartOrStop();
break;
}
}
}
}
android端的socket相關代碼(現學現用,大家見諒。。):
package com.android.baofengControl;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import android.content.Context;
import android.widget.TextView;
public class Client {
Socket client;
PrintWriter out;
TextView txt;
Context context;
public Client(TextView txt,Context context)
{
this.txt=txt;
this.context=context;
}
///建立連接,並保持
public void connectServer(String ip)
{
InetAddress serverAddress = null;
try {
serverAddress = InetAddress.getByName(ip);
} catch (UnknownHostException e) {
txt.setText(e.getLocalizedMessage()+txt.getText());
e.printStackTrace();
}
try {
client=new Socket(serverAddress,12121);
out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())),true);
} catch (IOException e) {
txt.setText(e.getLocalizedMessage()+txt.getText());
e.printStackTrace();
}
}
//發送消息
public void sendMsg(String msg) throws IOException
{
out.println(msg);
}
//發送over結束字符,然后斷開連接
public void close()
{
out.println("over");
out.close();
txt.setText("end"+txt.getText());
}
}
三,搖晃手機控制播放
這里使用了網上已有的代碼,稍加修改。
package com.android.baofengControl;
import java.io.IOException;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
public class MySensor {
SensorManager sensorManager;
Client client;
///開始監聽加速傳感器
public void Listen(SensorManager sensorManager,Client client)
{
this.client=client; //發送聯網數據的類。
this.sensorManager=sensorManager;
Sensor sensor=sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(sensorEventListener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
}
SensorEventListener sensorEventListener =new SensorEventListener(){
long lastUpdate,lastShakeTime = 0;
float x,y,last_x = 0,last_y = 0;
static final int SHAKE_THRESHOLD = 750;
public void onAccuracyChanged(android.hardware.Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
public void onSensorChanged(SensorEvent e) {
long curTime = System.currentTimeMillis();
// detect per 100 Millis
if ((curTime - lastUpdate) > 100) {
long diffTime = (curTime - lastUpdate);
lastUpdate = curTime;
//這里做了簡化,沒有用z的數據
x = e.values[SensorManager.DATA_X];
y = e.values[SensorManager.DATA_Y];
//z = Math.abs(values[SensorManager.DATA_Z]);
float acceChangeRate = 0;// = Math.abs(x+y - last_x - last_y) / diffTime * 1000;
if(last_x != 0) acceChangeRate = Math.abs(x+y - last_x - last_y) / diffTime * 10000;
//這里設定2個閥值,一個是加速度的,一個是shake的間隔時間的
if (acceChangeRate > SHAKE_THRESHOLD && curTime - lastShakeTime > 1000) {
lastShakeTime = curTime;
try {
client.sendMsg("stsp"); //發送消息。。。。。。。。。。。。。。。
} catch (IOException e1) {
e1.printStackTrace();
}
}
last_x = x;
last_y = y;
}
}};
}
最后,運行程序,然后可以按home鍵隱藏,只要要一下手機就可以控制暴風了。我的是2.3.7系統,測試通過。
