http://www.cnblogs.com/fmnisme/archive/2012/02/24/2363223.html
不知道大家有没有和我一样的习惯,喜欢躺在床上看电影,手里还拿着手机玩。。。
所以我就想到了这样一个程序:用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 向非顶端窗体发送组合键。
上面的这个方法模拟在暴风影音上按下,松开空格键。
下面是完整的代码
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;
namespace 暴风control
{
public class SendMsg
{
[DllImport("user32.dll", EntryPoint = "PostMessage")] //使用系统的非托管代码。
public static extern int PostMessage(
IntPtr hwnd,
int wMsg,
uint wParam,
uint lParam
);
IntPtr mainWindowHander;
/// <summary>
/// 遍历电脑所有的进程,获取暴风影音句柄
/// </summary>
public SendMsg()
{
Process[] allProcesses = Process.GetProcesses();
foreach (Process p in allProcesses)
{
if (p.ProcessName == "StormPlayer") //最新版暴风的进程名是StormPlayer,以前的是Storm在任务管理器里可以看到,这里不一样要修改一下。
mainWindowHander = p.MainWindowHandle;
}
if (mainWindowHander == IntPtr.Zero)
{
Process p = new Process();
p.StartInfo.FileName = @"D:\Baofeng\StormPlayer\StormPlayer.exe"; //暴风影音地址,改成你们自己的。
p.Start();
Thread.Sleep(3000); //这里是笨方法,要等待3秒,以免暴风影音进程还没有启动就获取句柄。
mainWindowHander = p.MainWindowHandle;
}
}
/// <summary>
/// 开始,暂停
/// </summary>
public void StartOrStop()
{
PostMessage(mainWindowHander, 0x0100, 0x20, 0x20390001);
PostMessage(mainWindowHander, 0x0101, 0x20, 0x20390001);
}
/// <summary>
/// 快退
/// </summary>
public void Back()
{
PostMessage(mainWindowHander, 0x0100, 0x25, 0x204b0001);
PostMessage(mainWindowHander, 0x0101, 0x25, 0x204b0001);
}
/// <summary>
/// 快进
/// </summary>
public void Qian()
{
PostMessage(mainWindowHander, 0x0100, 0x27, 0x204d0001);
PostMessage(mainWindowHander, 0x0101, 0x27, 0x204d0001);
}
}
}
二,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系统,测试通过。