[译]Libgdx在iOS平台的新特性

原文链接THE FUTURE OF LIBGDX ON IOS

翻译原文链接:http://www.maiyang.me/posts/2013/09/11/the-future-of-libgdx-on-ios

简单翻译一下,如果有任何错误或不对的地方,请指正。

The latest Xamarin update, which brought us Mono 3.0, breaks our libgdx iOS backend. More precisely, it breaks the IVKM Monotouch port by Michael Bayne, on which we rely to run our JVM bytecode on iOS. Michaels already working fixed up most things, but there are still some bumps on the way to a fully working version, which requires the assistance of Xamarin.

最新版的Xamarin带来了Mono 3.0,破坏了我们的libgdx的iOS后台,更确切的说,它打破了Michael Bayne的IVKM Monotouch的端口。 我们依靠在iOS上运行的JVM字节码。Michael已经修复很多事情,但仍然有一个完整的工作版本需要Xamarin去协助,在过程中有些颠簸。

Seeing how every update of Xamarin breaks our iOS backend, i can no longer promote this solution with good conscience. My skills and time budget are insufficient to support Michael, and not being able to fix things myself makes me really uncomfortable. The code i contributed to IKVM Monotouch was trivial compared to what Michael pulled off.

看到Xamarin每次更新如何打破我们的iOS后台,我再也不能具有良好的良知来推动这个解决方案了。我的技能和时间预算不足于支持Michael,不能够自己解决的事情,我真的很不舒服。相较于Michael的努力,我对IKVM Monotouch编程的付出简直是不值一提。

For this reason i’m announcing the deprecation of the Xamarin based iOS backend. Here’s how that will go down: We’ll push out the 0.9.9 release in the coming weeks, containing the stable IKVM monotouch port that is compatible with the previous release of Xamarin iOS (6.2.7.1). We’ll tag the release as always, the remove any signs of the Xamarin backend from the repository as well as our build system. This will simplify our build considerably We’ll create a replacement for the setup-ui, which is long overdue, and update the documentation were necessary. If you are currently working on a game, you should avoid updating to the latest Xamarin iOS version. Stick to libgdx 0.9.8, or the upcoming 0.9.9, or any nightly release in between those two versions.. If you already updated Xamarin iOS, you can downgrade to a working version (6.2.7.1 pkg) as discussed in this issue. We will start packaging the RoboVM backend starting with 0.9.9, which should now have feature parity with the Xamarin backend, thanks to a metric ton of hard work by Niklas Therning, creator of RoboVM. You should be able to “port” your game to that backend without huge problems (ymmv).

出于这个原因,我宣布弃用Xamarin基于iOS的后台。 这里,将如何往下走:

在未来几周内,我们将推出0.9.9版本,含有稳定的IKVM MonoTouch的端口,兼容以前的版本(6.2.7.1)Xamarin的iOS。 我们会标记release,一如既往地删除任何迹象Xamarin后端的储存库,以及构建系统。这将相当简化我们的构建。 我们将为setup-ui创建一个更换,这是期待已久的更换和更新的文件是必要的。 如果您目前正工作在一个游戏上,你应该避免更新Xamarin到最新的iOS版本。坚持libgdx0.9.8或0.9.9的到来,或任何在这两个版本之间的nightly release..如果您已经更新Xamarin的iOS,你可以降级到一个工作版本(6.2.7.1 PKG)在这个问题上讨论。 我们将从0.9.9开始包装RoboVM后端,现在应该有奇偶校验功能与Xamarin后端,谢谢由RoboVM的创作者Niklas Therning付出的巨大努力。你应该没有很大的问题就能够“移植”你的游戏(因人而异)。

>> 继续阅读 <<

仿pinterest瀑布流KISSY的Waterfall浏览器兼容问题

瀑布流概述

瀑布流案例

  1. pinterest-瀑布流的开山鼻祖
  2. Tumblr
  3. 花瓣网-国内做的很不错的瀑布流
  4. 其他各行各业都有所涉及

瀑布流组件

官方网站简单介绍了怎么样一步一步的入门,并且还给我们配备了在线demo。但是它有个很大的缺陷,就是在网络状况不好的时候,它的布局非常糟糕。

  • KISSY是由阿里集团前端工程师们发起创建的一个开源 JS 框架。它具备模块化、高扩展性、组件齐全,接口一致、自主开发、适合多种应用场景等特性。在KISSY内部有提供一个瀑布流组件Waterfall,并且也为我们配备了demo和它的完整教程

    有关它的使用,我在这里不做详细描述,请参照demo和教程去试验。

  • 其他,比方说花瓣网的瀑布流实现就非常牛逼,不仅完成了瀑布流的工作,而且还处理页面上的数据存储,避免因为大数据量时造成页面的卡顿情况的发生。
>> 继续阅读 <<

兼容android2.1以上flash视频播放的完美解决方案

通过androi官方文档,android是在2.1以后的版本开始支持flash视频播放的。 参见官方说明。

既然官方都不支持了,那我们再研究flash播放器就显得毫无必要,所以我们的解决方案主要是靠android提供的WebView,可浏览网页的内置组件来播放flash。

adobe官方关于OBJECT tag syntax说明 上面有详细的说明,我这里就不详细解释了,如果有不明白的,欢迎联系。

了解清楚解决方案中的核心用法之后继续下一步就水到渠成了。

主要分为以下几个步骤:

  1. 创建android项目
  2. 创建一个用于播放flash的activity ``` package com.ftxgame.ftxplatform.activity;

import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List;

import android.annotation.SuppressLint; import android.app.Activity; import android.app.ActivityManager; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Handler; import android.util.DisplayMetrics; import android.util.Log; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebSettings.PluginState; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.FrameLayout;

import com.ftxgame.ftxplatform.R; import com.umeng.analytics.MobclickAgent;

@SuppressLint(“NewApi”) public class FTXVideoActivity extends Activity {

private FrameLayout mFullscreenLayout;
private FrameLayout mContentLayout;

private String mUrl;
private View mCustomView = null;
private WebView mWebView;
private Intent intent;
private boolean hasAdobePlayer = false;// ADOBE FLASH PLAYER插件安装状态
private Context mContext;
private ProgressDialog mProgressDialog;

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	// 隐藏标题栏
	this.requestWindowFeature(Window.FEATURE_NO_TITLE);
	// 隐藏状态栏
	this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
			WindowManager.LayoutParams.FLAG_FULLSCREEN);

	initView();
	initWebView();
	
	DisplayMetrics dm = this.getResources().getDisplayMetrics();
	int widthScreen = dm.widthPixels/2;
	int heightScreen = dm.heightPixels/2;

	if (onCheck() == true) {
		StringBuilder html = new StringBuilder(1000);
		html.append("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />")
		.append("<style type='text/css'>")
		.append("html,body{margin:0px;padding:0px;}")
		.append("*{margin:0px;padding:0px;}</style>")
		.append("</head><body>")
		
		.append("<object width=\""+widthScreen+"\" height=\""+heightScreen+"\" type=\"application/x-shockwave-flash\" name=\"qzshareFlash\" id=\"qzshareFlash\" data=\""+mUrl+"\" class=\"video_play\">")
		.append("<param name=\"movie\" value=\""+mUrl+"\">")
		.append("<param value=\"always\" name=\"allowScriptAccess\">")
		.append("<param value=\"all\" name=\"allowNetworking\">")
		.append("<param value=\"true\" name=\"allowFullScreen\">")
		.append("<param value=\"opaque\" name=\"wmode\">")
		.append("</object></body></html>");
		showProgress();
		mWebView.loadData(html.toString(), "text/html", "UTF-8");
	} else {
		new AlertDialog.Builder(this)
				.setIcon(R.drawable.ic_launcher)
				.setTitle("温馨提醒:")
				.setMessage("Flash Player未安装或版本过低,请下载安装新版本后重试~")
				.setPositiveButton("重试",
						new DialogInterface.OnClickListener() {

							@Override
							public void onClick(DialogInterface dialog,
									int which) {
								intent.setClass(FTXVideoActivity.this,
										FTXVideoActivity.class);
								startActivity(intent);
							}
						})
				.setNegativeButton("退出",
						new DialogInterface.OnClickListener() {

							@Override
							public void onClick(DialogInterface dialog,
									int which) {
								ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
								am.restartPackage(getPackageName());
								intent.setClass(FTXVideoActivity.this,
										FTXVideoActivity.class);
								Intent i = new Intent(Intent.ACTION_MAIN);
								i.addCategory(Intent.CATEGORY_HOME);
								intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
								startActivity(intent);
								startActivity(i);
							}
						}).show();
	}
}

private void initView() {
	setContentView(R.layout.videoview);
	mContext = FTXVideoActivity.this;
	mFullscreenLayout = (FrameLayout) findViewById(R.id.fullscreen_custom_content);
	mContentLayout = (FrameLayout) findViewById(R.id.main_content);
	mWebView = (WebView) findViewById(R.id.video_view);

	if (getPhoneAndroidSDK() >= 14) {// 4.0需打开硬件加速
		getWindow().setFlags(0x1000000, 0x1000000);
	}
	
	intent = getIntent();
	mUrl = intent.getStringExtra("videoUrl");
}

/**
 * WebView相关设置
 */
private void initWebView() {
	WebSettings settings = mWebView.getSettings();
	settings.setJavaScriptEnabled(true);
	settings.setJavaScriptCanOpenWindowsAutomatically(true);
	settings.setPluginState(PluginState.ON);
	settings.setPluginsEnabled(true);
	settings.setAllowFileAccess(true);
	settings.setLoadWithOverviewMode(true);

	mWebView.setWebChromeClient(new MyWebChromeClient());
	mWebView.setWebViewClient(new MyWebViewClient());
}

public static int getPhoneAndroidSDK() {
	int version = 0;
	try {
		version = Integer.valueOf(android.os.Build.VERSION.SDK);
	} catch (NumberFormatException e) {
		e.printStackTrace();
	}
	return version;
}

/**
 * 判断是否安装ADOBE FLASH PLAYER插件
 * 
 * @return
 */
public boolean onCheck() {
	// 判断是否安装ADOBE FLASH PLAYER插件
	PackageManager pm = getPackageManager();
	List<PackageInfo> lsPackageInfo = pm.getInstalledPackages(0);

	for (PackageInfo pi : lsPackageInfo) {
		if (pi.packageName.contains("com.adobe.flashplayer")) {
			hasAdobePlayer = true;
			break;
		}
	}
	// 如果插件安装一切正常
	if (hasAdobePlayer == true) {
		return true;
	} else {
		return false;
	}
}

private void showProgress() {
	if(mProgressDialog == null){
		mProgressDialog = ProgressDialog.show(mContext, null, mContext.getString(R.string.loading));
	}else if(!mProgressDialog.isShowing()){
		mProgressDialog.show();
	}
}

private void hideProgress() {
		if (mProgressDialog != null && mProgressDialog.isShowing()) {
			mProgressDialog.dismiss();
		}
}

private void callHiddenWebViewMethod(String name) {
	if (mWebView != null) {
		try {
			Method method = WebView.class.getMethod(name);
			method.invoke(mWebView);
		} catch (NoSuchMethodException e) {
			Log.i("No such method: " + name, e.toString());
		} catch (IllegalAccessException e) {
			Log.i("Illegal Access: " + name, e.toString());
		} catch (InvocationTargetException e) {
			Log.d("Invocation Target Exception: " + name, e.toString());
		}
	}
}

class MyWebChromeClient extends WebChromeClient {
	
	private CustomViewCallback mCustomViewCallback;
	private int mOriginalOrientation = 1;
	
	@Override
	public void onShowCustomView(View view, CustomViewCallback callback) {
		Log.i("FTXVideoActivity", "onShowCustomView");
		onShowCustomView(view, mOriginalOrientation, callback);
		super.onShowCustomView(view, callback);
	}

	public void onShowCustomView(View view, int requestedOrientation,
			WebChromeClient.CustomViewCallback callback) {
		if (mCustomView != null) {
			callback.onCustomViewHidden();
			return;
		}
		Log.i("FTXVideoActivity", mOriginalOrientation+"");
		if (getPhoneAndroidSDK() >= 14) {
			mFullscreenLayout.addView(view);
			mCustomView = view;
			mCustomViewCallback = callback;
			mOriginalOrientation = getRequestedOrientation();
			mContentLayout.setVisibility(View.INVISIBLE);
			mFullscreenLayout.setVisibility(View.VISIBLE);
			mFullscreenLayout.bringToFront();

			setRequestedOrientation(mOriginalOrientation);
		}
		Log.i("FTXVideoActivity", mOriginalOrientation+"");
	}

	public void onHideCustomView() {
		Log.i("FTXVideoActivity", "onHideCustomView");
		mContentLayout.setVisibility(View.VISIBLE);
		if (mCustomView == null) {
			return;
		}
		mCustomView.setVisibility(View.GONE);
		mFullscreenLayout.removeView(mCustomView);
		mCustomView = null;
		mFullscreenLayout.setVisibility(View.GONE);
		try {
			mCustomViewCallback.onCustomViewHidden();
		} catch (Exception e) {
			Log.e("FTXVideoActivity", e.getMessage());
		}
		// Show the content view.
		setRequestedOrientation(mOriginalOrientation);
	}
	
	@Override
	public void onProgressChanged(WebView view, int newProgress) {
		super.onProgressChanged(view, newProgress);
		if(100 == newProgress) {				
			hideProgress();
		}
	}

}

class MyWebViewClient extends WebViewClient {

	@Override
	public boolean shouldOverrideUrlLoading(WebView view, String url) {
		view.loadUrl(url);
		Log.i("FTXVideoActivity", "shouldOverrideUrlLoading");
		return super.shouldOverrideUrlLoading(view, url);
	}
	
	@Override
	public void onPageFinished(WebView view, String url) {
		super.onPageFinished(view, url);
		hideProgress();
		Log.i("FTXVideoActivity", "onPageFinished");
	}
} } ``` 3. 创建layout.xml ``` <?xml version="1.0" encoding="utf-8"?>

``` 一个兼容android2.1以上系统的flash播放解决方案就完成了。

后面经过我的全面兼容性测试,可能会有以下问题:

  1. android系统自身已经安装adobe flash player 11或之前版本,在android4.1之前的老系统上可能是正常的,但是在新系统上会存在问题,或许还包括4.0系统,因为资源问题,我就无法测试到位,希望有朋友能给我测试的反馈。
  2. android4.0以上系统全屏支持不够好,android2.3.5基本上可以说是完美播放。
  3. android2.2系统是不支持flash11.1的,所以我们在提示播放的时候要安装对应的版本。
>> 继续阅读 <<

IE下JS错误“尚未实现”

###IE下JS错误“尚未实现”解决办法

今天在开发一个功能时,使用到了onpaste=check();,在FF,Chrome下一切都正常,但是当我用IE8测试的时候,总给我提示JS错误。 错误信息为“尚未实现”,无论怎么搞就搞不定。诡异的是在chrome和FF的调试模式下没有看到任何错误提示。

一打开IE8就遇到这个该死的“尚未实现”错误,根据IE8中提示的位置找过去也没有明白其发生了什么错误。

万般无奈之下,google搜索,终于找到了错误所在的地方。

根据文中所说,

原来错误在于window.onload= myFunc(var1,var2);IE的window.onload函数中不支持参数调用,虽然函数会照样执行,但是却会出现报错,影响后续脚本的继续执行,下面是两种简单而有用的解决办法:

  1. 再写一个函数,譬如function loadFunc(){ myFunc(var1,var2) },然后window.onload = loadFunc;
  2. 使用匿名函数。onload =function(){myFunc(var1,var2)}

所以依葫芦画瓢,我们的onpaste方法肯定也是不支持参数调用的。

>> 继续阅读 <<

我的博客域名历程

一直以来我自己都很想拥有自己的私有博客,虽然现在有很多的技术社区和博客站点都提供有,但是总觉得那不是自己想要的,直到最近我发现了logdown.com这个为hackers量身定做的产品时,我再也压抑不住自己想创造的激情了。 我自己在各个时期都有博客的,有些是个人知识备忘,有些是个人生活。 hi百度空间:Mai cnblog,51cto,ITEye,oschina.net,roon.io,writings.io,jianshu.io等等。

现在我就说说我的博客和个人域名整个历程吧。

以下几个必须步骤:

  1. 域名提供商
  2. 资金(网银/支付宝)
  3. 个人域名名称以及域名
  4. 可自定义域名的博客

接下来是逐步把他们串联起来。

##开始–我是怎么开始准备的呢?

  • 个人一直都在使用淘宝,所以支付宝也就不麻烦了。
  • 开始是创建了一个个人博客,可能你们会疑问为什么要选择logdown这个博客服务呢?我不做详解,有需要的朋友可以跟我私下沟通。O(∩_∩)O哈哈
  • 个人域名名称,我的英文名一直是mai,姓yang,所以这个由来也很自然
  • 最重点的域名提供商的选择,我就是网上随便一搜索,看到了万网,然后也知道这个是马云在很早之前做过的,现在也是阿里巴巴集团下的一个业务,所以也没多想就决定在这儿了。

##进行–域名申请 >> 继续阅读 <<

个人开发项目

maitodo

一个简单的TODO应用,基于nodejs、express、ejs、mongodb开发。

地址是:

GifImageViewEx

android解析本地或者URL的gif图片或者jpg、png等图片,基于ImageViewEx。

地址是:

1、本地gif读取播放 2、本地jpg/png图片读取 3、URL gif图片读取播放 4、URL jpg/png 图片读取

github:https://github.com/yangwenmai twitter:https://twitter.com/yangwenmai facebook:https://www.facebook.com/yangwenmai sina_weibo:http://weibo.com/yangwen0o0

>> 继续阅读 <<

饭特稀体育产品思考

#网站改造想法 ###一、网站赢利点考虑 重点 ###二、从视频和科普文章着手

  1. 增加原创视频–渠道:优酷或土豆,新浪
  2. 增加一些篮球,足球,其他体育类别的科普文章,用图文并茂的形式来展现,或者以期刊的形式
  3. 可以在科普文章的同时增加一些交互,比如科普问答,奖励积分等

###三、直播和数据

  1. 直播,不仅仅只有赛事预告,还应该添加(文字和音频,视频直播)
  2. 球队、球员数据库(不在乎发明重复的轮子,而在于重复的东西有没有意义和价值,是否有提升和创新),
  3. 也可以将1和2两者结合起来,比方说,一场比赛,我们可以提供链接球队,也可以查看球队近期战绩,球队球员表现情况等,我们还可以主动向篮球游戏找资源,是否可以拿到每日涨幅榜之类的统计数据。

#其他方面改造 ###1.微信平台扩展 微信平台干过了微博(新浪和腾讯微博),我觉得我们可以花一定的精力在这个开放平台上,做微信企业号或者订阅号,做一些专题或者精品上去,增加粉丝量和曝光度,做一定的深度开发

###2.地域体育新闻和游戏娱乐圈新闻 比方说,国外华盛顿,纽约,休斯顿,伦敦,巴黎,马德里,国内北京,上海,广州,深圳等等不同地方体育新闻和体育游戏类新闻以及其他花边娱乐新闻。增加一个类似区域版块的东西,让不同地方的人积聚在一起,畅聊,共享,发起活动等。提供一体化的球迷娱乐社区。 ###3.增加社区分享 增加国外社区分享,吸引部分优质的华侨和高端用户,维系一个公共twitter和facebook。 ###4.增强互动以及活动 增强意见反馈,

网站所有的交互功能都进行重构,以简单轻便的参与为核心目标,

不定期的举办活动吸引用户的参与,可以是实体奖品,也可以去协调一些游戏资源道具的奖励,等等。 >> 继续阅读 <<

第三方登录使用过程中的总结


SSO授权优势:不需要重复输入新浪微博用户名、密码,只需要一步操作,直接点击授权按钮即可完成授权,增强了操作简便性及帐号安全性。


1. 新浪微博

1、整合准备

2、整合分析

  • 根据官方使用手册将需要应用信息整合到自己的应用代码中。

    • 后台接口需要支持第三方登录的识别和支持,目前接口是parterLogin

3、注意事项

>> 继续阅读 <<

图片查看、gif播放、swf视频播放的开发总结

图片查看、gif播放、swf视频播放的开发总结


图片是分为多种类型的,并且他们在android上是非常耗内存的,所以我们在进行图片查看的时候也要注意不同类型和不同尺寸进行不同的处理。

例如:gif处理,主要涉及到gif图片类型获取,以及gif播放处理。


1、图片查看

  • 根据类型分为动态图(gif)和静态图(jpg/png)

  • 根据大小显示分为正常显示和Web显示

2、gif处理

##1、gif图片类型 ##

  • gif图片类型处理

    代码如下:

>> 继续阅读 <<

【转】App Store审核宝典

讲流程之前,首先提醒大家,最好是下载苹果自己出品的ITC MoblieITC Mobile, 方便在移动状态下浏览收益是一方面,提交App以后最及时的获得审核进度是另外一方面,下载ITC Moblie后,登入自己的ITC后台,就可以在审核状态发生变化的时候获得推通知。很多时候,尽早知道状态有利于尽早处理。例如,我们在中国区,但是审核员在美国,经常是晚上12点到1点的时候,得知被拒,如果你可以在10-20分钟内回应,那么审核员还没下班,也许就可以立即解决,如果你等到明天早晨解决的话,明天的深夜审核员才会看到你的回复。 本文主要是介绍审核应对,所以,从App已经提交讲起。

appsubmitprocess_m

>> 继续阅读 <<