android遥控器:控制电脑上的暴风影音播放(C#作为服务端)

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系统,测试通过。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值