package com.guo.duoduo.airplayreceiver.service;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.InetAddress;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.HashMap;
import java.util.Locale;
import javax.jmdns.JmDNS;
import javax.jmdns.ServiceInfo;
import android.app.Service;
import android.content.Intent;
import android.content.res.Resources;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.widget.Toast;
import com.guo.duoduo.airplayreceiver.MyApplication;
import com.guo.duoduo.airplayreceiver.MyController;
import com.guo.duoduo.airplayreceiver.R;
import com.guo.duoduo.airplayreceiver.constant.Constant;
import com.guo.duoduo.airplayreceiver.httpProcess.HttpProcess;
import com.guo.duoduo.airplayreceiver.httpcore.RequestListenerThread;
import com.guo.duoduo.airplayreceiver.rtsp.LaunchThread;
import com.guo.duoduo.airplayreceiver.ui.ImageActivity;
import com.guo.duoduo.airplayreceiver.ui.VideoPlayerActivity;
import com.guo.duoduo.airplayreceiver.utils.NetworkUtils;
/**
* Created by Guo.DUO duo on 2015/8/27.
*/
public class RegisterService extends Service
{
public static final int AIRPLAY_PORT = 8192;
public static final int RAOP_PORT = 5000;
private static final String tag = RegisterService.class.getSimpleName();
private static final String airplayType = "._airplay._tcp.local";
private static final String raopType = "._raop._tcp.local";
private String airplayName = "郭攀峰";
private MyController myController;
private ServiceHandler handler;
private InetAddress localAddress;
private JmDNS jmdnsAirplay = null;
private JmDNS jmdnsRaop;
private ServiceInfo airplayService = null;
private ServiceInfo raopService;
private HashMap<String, String> values = new HashMap<String, String>();
private String preMac;
private RequestListenerThread thread;
private HttpProcess httpProcess;
private LaunchThread raopThread;
public static PrivateKey pk;
private WifiManager.MulticastLock lock;
@Override
public void onCreate()
{
super.onCreate();
Log.d(tag, "register service onCreate");
WifiManager wifi = (android.net.wifi.WifiManager) getSystemService(android.content.Context.WIFI_SERVICE);
lock = wifi.createMulticastLock("mylockthereturn");
lock.setReferenceCounted(true);
lock.acquire();
try
{
Resources resources = this.getResources();
InputStream is = resources.openRawResource(R.raw.key);
pk = KeyFactory.getInstance("RSA").generatePrivate(
new PKCS8EncodedKeySpec(getByteArrayFromStream(is)));
}
catch (Exception e)
{
throw new IllegalStateException(e);
}
airplayName = android.os.Build.MODEL + "@" + airplayName;
handler = new ServiceHandler(RegisterService.this);
myController = new MyController(RegisterService.class.getName(), handler);
Toast toast = android.widget.Toast.makeText(getApplicationContext(),
"正在注册Airplay服务...", android.widget.Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
new Thread()
{
public void run()
{
try
{
thread = new RequestListenerThread();
thread.setDaemon(false);
thread.start();
registerAirplay();
// httpProcess = new HttpProcess();
// httpProcess.setHTTPPort(RegisterService.AIRPLAY_PORT);
// httpProcess.start();
//
// raopThread = new LaunchThread(RAOP_PORT);
// raopThread.start();
}
catch (IOException e)
{
e.printStackTrace();
Message msg = Message.obtain();
msg.what = Constant.Register.FAIL;
MyApplication.broadcastMessage(msg);
return;
}
}
}.start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy()
{
Log.d(tag, "RegisterService onDestroy");
super.onDestroy();
myController.destroy();
lock.release();
new Thread()
{
public void run()
{
if (thread != null) //airplay关闭服务很慢,将thread关闭放在前面
thread.destroy();
// if (httpProcess != null)
// httpProcess.stop();
//
// if (raopThread != null)
// {
// raopThread.destroy();
// }
try
{
unregisterAirplay();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}.start();
}
@Override
public IBinder onBind(Intent intent)
{
return null;
}
private void registerAirplay() throws IOException
{
Message msg = Message.obtain();
if (!getParams())
{
msg.what = Constant.Register.FAIL;
}
else
{
register();
Log.d(tag, "airplay register airplay success");
}
msg.what = Constant.Register.OK;
MyApplication.broadcastMessage(msg);
}
private void register() throws IOException
{
Log.d(tag, "airplay register");
registerTcpLocal();
registerRaopLocal();
}
private void registerTcpLocal() throws IOException
{
airplayService = ServiceInfo.create(airplayName + airplayType, airplayName,
AIRPLAY_PORT, 0, 0, values);
jmdnsAirplay = JmDNS.create(localAddress);//create的必须绑定ip地址 android 4.0以上
jmdnsAirplay.registerService(airplayService);
}
private void registerRaopLocal() throws IOException
{
String raopName = preMac + "@" + airplayName;
raopService = ServiceInfo.create(raopName + raopType, raopName, RAOP_PORT,
"tp=UDP sm=false sv=false ek=1 et=0,1 cn=0,1 ch=2 ss=16 "
+ "sr=44100 pw=false vn=3 da=true md=0,1,2 vs=103.14 txtvers=1");
jmdnsRaop = JmDNS.create(localAddress);
jmdnsRaop.registerService(raopService);
}
private boolean getParams()
{
String strMac = null;
try
{
Thread.sleep(2 * 1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
localAddress = NetworkUtils.getLocalIpAddress();//获取本地IP对象
if (localAddress == null)
{
Log.d(tag, "local address = null");
return false;
}
String[] str_Array = new String[2];
try
{
str_Array = NetworkUtils.getMACAddress(localAddress);
if (str_Array == null)
return false;
strMac = str_Array[0].toUpperCase(Locale.ENGLISH);
preMac = str_Array[1].toUpperCase(Locale.ENGLISH);
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
Log.d(tag, "airplay 注册Airplay Mac地址:" + strMac + "; preMac = " + preMac);
values.put("deviceid", strMac);//修改为mac地址
values.put("features", "0x297f"); //
values.put("model", "AppleTV2,1");//
values.put("srcvers", "130.14");
return true;
}
private void unregisterAirplay()
{
Log.d(tag, "un register airplay service");
if (jmdnsAirplay != null)
{
jmdnsAirplay.unregisterService(airplayService);
try
{
jmdnsAirplay.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
if (jmdnsRaop != null)
{
jmdnsRaop.unregisterService(raopService);
try
{
jmdnsRaop.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
private byte[] getByteArrayFromStream(InputStream is) throws IOException
{
byte[] b = new byte[10000];
int read;
ByteArrayOutputStream out = new ByteArrayOutputStream();
while ((read = is.read(b, 0, b.length)) > 0)
{
out.write(b, 0, read);
}
return out.toByteArray();
}
private static class ServiceHandler extends Handler
{
private WeakReference<RegisterService> weakReference;
public ServiceHandler(RegisterService service)
{
weakReference = new WeakReference<RegisterService>(service);
}
@Override
public void handleMessage(Message msg)
{
super.handleMessage(msg);
RegisterService service = weakReference.get();
if (service == null)
return;
switch (msg.what)
{
case Constant.Register.OK :
{
Toast toast = Toast.makeText(service.getApplicationContext(),
"Airplay注册成功", android.widget.Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
break;
case Constant.Register.FAIL :
{
Toast toast = Toast.makeText(service.getApplicationContext(),
"Airplay注册失败", android.widget.Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
service.stopSelf();
android.os.Process.killProcess(android.os.Process.myPid()); //完全退出程序
break;
}
case Constant.Msg.Msg_Photo :
{
byte[] pic = (byte[]) msg.obj;
Intent intent = new Intent(service, ImageActivity.class);
intent.putExtra("picture", pic);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
service.startActivity(intent);
break;
}
case Constant.Msg.Msg_Video_Play :
{
HashMap<String, String> map = (HashMap) msg.obj;
String playUrl = map.get(Constant.PlayURL);
String startPos = map.get(Constant.Start_Pos);
Intent intent = new Intent(service, VideoPlayerActivity.class);
intent.putExtra("path", playUrl);
intent.putExtra("position", Double.valueOf(startPos));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
service.startActivity(intent);
break;
}
}
}
}
}