package com.joyplus.ad;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.Thread.UncaughtExceptionHandler;
import java.net.MalformedURLException;
import java.net.URL;
import android.content.Context;
import android.location.Location;
import com.joyplus.adkey.AdRequest;
import com.joyplus.adkey.Const;
import com.joyplus.adkey.RequestRichMediaAd;
import com.joyplus.adkey.Util;
import com.joyplus.adkey.download.ImpressionThread;
import com.joyplus.adkey.video.ResourceManager;
import com.joyplus.adkey.video.RichMediaAd;
import com.joyplus.adkey.video.VideoData;
import com.joyplus.adkey.widget.SerializeManager;
import com.joyplus.tvhelper.utils.Log;
public class AdvertManager {
private boolean Debug = false;
private String TAG = "AdvertManager";
private boolean mIncludeLocation = false;
private String mRequestURL = null;
private SerializeManager serializeManager;
private Context mContext;
private String PUBLISHERID = null;
private String mUniqueId1;
private String mUniqueId2;
private String mUserAgent;
private boolean mEnabled = false;
private AdRequest mAdRequest = null;
private Thread mRequestThread;
private RichMediaAd mRichMediaAd; // respone media
private AdListener mListener;
public void setListener(AdListener listener) {
mListener = listener;
}
// this should be the same as it in BootAnimation.cpp
public static String DefaultFILEPATH = "JoyplusAd";
public String getPlayUri(){
if(PATH == null)return null;
File file = new File(PATH);
if (file.exists()) {
String[] temp = file.list();
if (temp != null) {
for (int i = 0; i < temp.length; i++) {
if (temp[i].contains(DefaultFILEPATH)) {
return PATH+temp[i];
}
}
}
}
return null;
}
private String DefaultAD = "tv_patch_advert";
private String PATH = null;
public AdvertManager(Context ctx, final String publisherId,
final boolean cacheMode) {
this.PUBLISHERID = publisherId;
this.PATH = Const.DOWNLOAD_PATH+ctx.getPackageName()+"/"+PUBLISHERID+"/";
DefaultAD = PATH+DefaultAD;
mContext = ctx;
Util.CACHE_MODE = cacheMode;
InitResource();
}
// Interface for user to Manager the resource.
public void UpdateAdvert() {
// resave advert file first.
ResaveCacheLoaded();
requestAd();
if (!WaitAd(20000)) {
notifyAdClose();
return;
}
// now we can download mp4 file and report count.
DownloadFile();
}
// Interface Report count
public void ReportCount() {
new Thread(new ReportCountRunnable()).start();
}
// Tnterface Download file
private void DownloadFile() {
new Thread(new DownloadFileRunnable()).start();
}
private class DownloadFileRunnable implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
RichMediaAd tempAd = (RichMediaAd) serializeManager
.readSerializableData(DefaultAD);
if (tempAd != null) {
VideoData video = tempAd.getVideo();
if (Util.CACHE_MODE && video != null) {
String Download_path = video.getVideoUrl();
URL url = null;
try {
url = new URL(Download_path);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (url != null) {
Util.ExternalName = "."
+ Util.getExtensionName(url.getPath());
} else {
Util.ExternalName = ".mp4";
}
Downloader downloader = new Downloader(Download_path,PATH);
if (Download_path.startsWith("http:")
|| Download_path.startsWith("https:")) {
downloader.download();
if (Debug)
Log.i(TAG, "download starting");
}
} else {
if (Debug)
Log.i(TAG, "download fail video url fail");
notifyAdNofound();
}
} else {
if (Debug)
Log.i(TAG, "download fail ad null");
notifyAdNofound();
}
}
}
private class ReportCountRunnable implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
if (Debug)
Log.d(TAG, "ReportCountRunnable run()");
new ImpressionThread(mContext, mRichMediaAd.getmImpressionUrl(),
PUBLISHERID, Util.AD_TYPE.FULL_SCREEN_VIDEO).start();
}
}
/* Wait for Ad return form Server,Time out : faslse , Result : true. */
private boolean WaitAd(int Time) {
// waiting for Ad result.
long now = System.currentTimeMillis();
long timeoutTime = now + Time;// 20s
while ((mRichMediaAd == null) && (now < timeoutTime)) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
now = System.currentTimeMillis();
}
if (mRichMediaAd == null) {// no Ad can use
notifyAdClose();
return false;
}
return true;
}
/* request Ad from Server */
private void requestAd() {
requestAd(null);
}
private void requestAd(final InputStream xml) {
if (Debug)
Log.i(TAG, "requestAd mEnabled=" + mEnabled +" mRequestThread="+(mRequestThread!=null));
if (!mEnabled)
return;
if (mRequestThread == null) {
mRichMediaAd = null;
mRequestThread = new Thread(new Request(xml));
mRequestThread
.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread,
Throwable ex) {
ex.printStackTrace();
mRichMediaAd = new RichMediaAd();
mRichMediaAd.setType(Const.AD_FAILED);
mRequestThread = null;
}
});
mRequestThread.start();
}
}
/* get Ad from Server */
private class Request implements Runnable {
private InputStream XML = null;
private RequestRichMediaAd requestAd;
public Request(InputStream xml) {
XML = xml;
}
@Override
public void run() {
// TODO Auto-generated method stub
while (ResourceManager.isDownloading()) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
}
try {
if (XML == null) {
requestAd = new RequestRichMediaAd();
} else {
requestAd = new RequestRichMediaAd(XML);
}
AdRequest request = getRequest();
File cacheDir = new File(PATH);
if (!cacheDir.exists())cacheDir.mkdirs();
mRichMediaAd = (RichMediaAd) serializeManager
.readSerializableData(DefaultAD);
RichMediaAd nextResponse = requestAd.sendRequest(request);
serializeManager.writeSerializableData(DefaultAD, nextResponse);
if (mRichMediaAd == null) {
mRichMediaAd = nextResponse;
}
} catch (Throwable t) {
Log.e(TAG,"Request error ");
t.printStackTrace();
mRichMediaAd = (RichMediaAd) serializeManager
.readSerializableData(DefaultAD);
} finally {
notifyResponse();
}
}
}
private void notifyResponse() {
if (mRichMediaAd == null) {
if (Debug)
Log.d(TAG, "notifyResponse() mReponse ==null ");
mRichMediaAd = new RichMediaAd();
mRichMediaAd.setType(Const.AD_FAILED);
}
if (mRichMediaAd.getType() == Const.VIDEO_TO_INTERSTITIAL
|| mRichMediaAd.getType() == Const.INTERSTITIAL_TO_VIDEO
|| mRichMediaAd.getType() == Const.VIDEO
|| mRichMediaAd.getType() == Const.INTERSTITIAL) {
notifyAdLoadSuccessed();
} else {
notifyAdNofound();
}
}
// get the AdRequest
private AdRequest getRequest() {
if (mAdRequest == null) {
mAdRequest = new AdRequest();
mAdRequest.setDeviceId(mUniqueId1);
mAdRequest.setDeviceId2(mUniqueId2);
mAdRequest.setPublisherId(PUBLISHERID);
mAdRequest.setUserAgent(mUserAgent);
mAdRequest.setUserAgent2(Util.buildUserAgent());
}
Location location = null;
if (this.mIncludeLocation) {
location = Util.getLocation(mContext);
}
if (location != null) {
mAdRequest.setLatitude(location.getLatitude());
mAdRequest.setLongitude(location.getLongitude());
} else {
mAdRequest.setLatitude(0.0);
mAdRequest.setLongitude(0.0);
}
mAdRequest.setConnectionType(Util.getConnectionType(mContext));
mAdRequest.setIpAddress(Util.getLocalIpAddress());
mAdRequest.setTimestamp(System.currentTimeMillis());
mAdRequest.setType(AdRequest.VAD);
mAdRequest.setRequestURL(this.mRequestURL);
return mAdRequest;
}
/*
* Resave advert file to default dir,make sure its same as BootAnimation.cpp
* support.
*/
private boolean ResaveCacheLoaded() {
// TODO Auto-generated method stub
File file = new File(PATH);
if (file.exists()) {
String[] temp = file.list();
if (temp != null) {
for (int i = 0; i < temp.length; i++) {
if (temp[i].contains(Const.DOWNLOAD_PLAY_FILE)) {
String dstFile = PATH+DefaultFILEPATH;
String extra = getExtensionName(temp[i]);
if(extra!=null && !extra.equals(temp[i])){
dstFile += ("."+getExtensionName(temp[i]));
}
copyFile(new File(PATH + temp[i]), new File(dstFile));
return true;
}
}
}
}
return false;
}
public static String getExtensionName(String filename) {
if ((filename != null) && (filename.length() > 0)) {
int dot = filename.lastIndexOf('.');
if ((dot >-1) && (dot < (filename.length() - 1))) {
return filename.substring(dot + 1);
}
}
return null;
}
private boolean copyFile(File srcFile, File dstFile) {
try {
InputStream in = new FileInputStream(srcFile);
if (dstFile.exists())
dstFile.delete();
OutputStream out = new FileOutputStream(dstFile);
try {
int cnt;
byte[] buf = new byte[4096];
while ((cnt = in.read(buf)) >= 0) {
out.write(buf, 0, cnt);
}
} finally {
out.close();
in.close();
}
if (Debug)
Log.d(TAG, "copyFile() success");
return true;
} catch (IOException e) {
if (Debug)
Log.d(TAG, "copyFile() fail");
return false;
}
}
private void InitResource() {
// TODO Auto-generated method stub
this.mIncludeLocation = true;
this.mRequestURL = Const.REQUESTURL;
Util.GetPackage(mContext);
serializeManager = new SerializeManager();
mUserAgent = Util.getDefaultUserAgentString(mContext);
this.mUniqueId1 = Util.getTelephonyDeviceId(mContext);
this.mUniqueId2 = Util.getDeviceId(mContext);
if ((PUBLISHERID == null) || (PUBLISHERID.length() == 0)) {
throw new IllegalArgumentException(
"User Id cannot be null or empty");
}
if ((mUniqueId2 == null) || (mUniqueId2.length() == 0)) {
throw new IllegalArgumentException(
"System Device Id cannot be null or empty");
}
mEnabled = (Util.getMemoryClass(mContext) > 16);
Util.initializeAnimations(mContext);
}
private synchronized void notifyAdLoadSuccessed() {
if (mListener == null)
return;
new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
mListener.adLoadSucceeded();
}
}.run();
}
private synchronized void notifyAdNofound() {
if (mListener == null)
return;
new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
mListener.noAdFound();
}
}.run();
}
private synchronized void notifyAdClose() {
if (mListener == null)
return;
new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
mListener.Closed();
}
}.run();
}
}