06
5

如何在Mono for android中添加友盟sdk,这个功能非常重要,他直接牵扯一个非常重要的问题:如何在mono for android的项目中引入jar包?考虑到android目前大量的应用都是基于java开发的,很多开源的类库和组件也是基于java开发的,所以如何在mono项目引入jar包非常关键,这是做mono for android应用开发的核心之一。我们在项目中已经成功地引入了jar包,几乎所有的包都可以引入和使用,这当然归功于xamarin公司的优秀产品。

在这里,我先介绍第一种方法:直接在app项目引入jar包,通过桥接语言调用。其实在实际项目中这种方式用得很少,但我强烈建议每一个C#程序员都尝试一次,因为他会让你对编程语言有更深一层次的理解。我以umeng_sdk.jar为例,这个包主要是用于统计app运行、安装等情况的。

step1:在项目添加现有文件,选择umeng_sdk.jar;

step2:将umeng_sdk.jar的属性Build Action,设置为AndroidJavaLibrary;

step3:创建一个类,如下所示

/// <summary>

/// Java libary helper.

/// java类库

/// </summary>

public static class JavaLibaryHelper

{

#region umeng class

private static IntPtr _umengHelperClass = JNIEnv.FindClass("com/umeng/analytics/MobclickAgent");

public static void UmengOnResume(Context context)

{

IntPtr methodId = JNIEnv.GetStaticMethodID(_umengHelperClass, "onResume", "(Landroid/content/Context;)V");

JNIEnv.CallStaticVoidMethod(_umengHelperClass, methodId,new JValue(context));

}

public static void UmengOnPause(Context context)

{

IntPtr methodId = JNIEnv.GetStaticMethodID(_umengHelperClass, "onPause", "(Landroid/content/Context;)V");

JNIEnv.CallStaticVoidMethod(_umengHelperClass, methodId,new JValue(context));

}

#endregion

}

这里做一下说明:

1、JNIEnv.FindClass("com/umeng/analytics/MobclickAgent")是通过中间语言调用java里面的对象,原型请参考umeng_sdk.jar的说明,能拥有这样的方式,完全得益于mono创始人的天才,他建立了c#和java之间的桥梁,并且不损失多大的效率!

2、JNIEnv.GetStaticMethodID(_umengHelperClass, "onResume", "(Landroid/content/Context;)V")是通过上面创建的对象,获取对象的方法,包括方法名和方法的签名,具体的语法,你可以通过查看mono for android类库的方法原型(右键转到定义);

3、CallStaticVoidMethod(_umengHelperClass, methodId,new JValue(context)),调用方法,并获得返回值,这里调用的是Void静态方法。

通过这次的实践,我觉得自己对编程语言,特别是C#、java这两种语言的了解更加深刻了,其实还有更好的方法去绑定jar包,下一篇我会介绍。

20
4

前面讲过,通过EmbeddedJar方式可以绑定jar包,这个在实践中已经证明没有问题了,但是绑定的过程中,可能会出现一些小错误,我在绑定讯飞语点的jar包的时候,就报了如下的错误:

Error message:

obj\Debug\generated\src\Com.Iflytek.Speech.SpeechRecognizer.cs(8,69,8,80): error CS0234: 命名空间“Com.Iflytek.Speech”中不存在类型或命名空间名称“SpeechBaser”(是否缺少程序集引用?)

obj\Debug\generated\src\Com.Iflytek.Speech.SpeechSynthesizer.cs(8,70,8,81): error CS0234: 命名空间“Com.Iflytek.Speech”中不存在类型或命名空间名称“SpeechBaser”(是否缺少程序集引用?)

obj\Debug\generated\src\Com.Iflytek.Speech.SpeechUnderstander.cs(8,71,8,82): error CS0234: 命名空间“Com.Iflytek.Speech”中不存在类型或命名空间名称“SpeechBaser”(是否缺少程序集引用?)

obj\Debug\generated\src\Com.Iflytek.Speech.TextUnderstander.cs(8,69,8,80): error CS0234: 命名空间“Com.Iflytek.Speech”中不存在类型或命名空间名称“SpeechBaser”(是否缺少程序集引用?)

IDE Version: xamarin.studio 4.0.3

当时几乎觉得无望的时候,给xamarin公司发了邮件,过了两天,他们回复了解决办法。他们的邮件说:这是mono for android的一个bug。幸亏给了解决办法:

在创建的类库(引用了jar包的类库)的Transforms文件夹下有个Metadata.xml,在这个文件里加入:

<attr path="/api/package[@name='com.iflytek.speech']/class[@name='SpeechBaser']" name="visibility">public</attr>
<attr path="/api/package[@name='com.iflytek.speech']/interface[@name='WakeuperListener']/method[@name='onVolumeChanged']" name="argsType">OnVolumeChangedEventArgs</attr>

就可以解决问题了,我相信其他类似的jar包也可以通过这种方式解决。

这也算是我为开源做的一次贡献,发现了一个bug,挺开心的!

另外,估计xamarin公司会在下一个版本解决这个bug,坚信他们能解决。

11
4

WebView是一个非常重要的控件,移动开发过程中会经常使用WebView来显示数据。WebView的使用非常简单,创建相应的对象,使用LoadData或者LoadUrl方法加载html数据,前者是价值html字符串,后者是加载一个可访问的URL地址。

这是基本应用,WebView还有两个高级应用,一个是显示加载的百分比,另外一个是支持返回按钮。

1、如何加载百分比

这里需要对WebView的方法进行重写,如下所示:

private class AwesomeWebClient : WebViewClient { }

private class AwesomeWebChromeClient : WebChromeClient

{

private Activity mParentActivity;

private string mTitle;

public AwesomeWebChromeClient(Activity parentActivity)

{

mParentActivity = parentActivity;

mTitle = parentActivity.Title;

}

public override void OnProgressChanged(WebView view, int newProgress)

{

mParentActivity.Title = string.Format("Loading {0}%", newProgress);

mParentActivity.SetProgress(newProgress * 100);

if (newProgress == 100) mParentActivity.Title = mTitle;

}

}

然后,调用相应的WebView方法:

newsWebView = FindViewById<WebView>(Resource.Id.newsWebView);

newsWebView.Settings.JavaScriptEnabled = true;

newsWebView.Settings.SetSupportZoom(true);

newsWebView.Settings.BuiltInZoomControls = true;

newsWebView.Settings.LoadWithOverviewMode = true; //Load 100% zoomed out

newsWebView.ScrollBarStyle = ScrollbarStyles.OutsideOverlay;

newsWebView.ScrollbarFadingEnabled = true;

newsWebView.VerticalScrollBarEnabled = true;

newsWebView.HorizontalScrollBarEnabled = true;

newsWebView.SetWebViewClient(new AwesomeWebClient());

newsWebView.SetWebChromeClient(new AwesomeWebChromeClient(this));

2、点击返回按钮后退网页

这个比较简单,重写OnKeyDown方法即可,如下所示:

public override bool OnKeyDown(Android.Views.Keycode keyCode, Android.Views.KeyEvent e)

{

if (keyCode == Keycode.Back && newsWebView.CanGoBack())

{

newsWebView.GoBack();

return true;

}

else

{

this.Finish();

return base.OnKeyDown(keyCode, e); 

}

}

10
4

设置Mono for android启动页

0
归档:2013年4月分类:开源Mono

移动应用都有应用启动页,在mono for android里,设置应用启动页非常简单。

1、在Style.xml里添加设置:

<resources>

<style name="Theme.Splash" parent="android:Theme">

<item name="android:windowBackground">@drawable/splash</item>

<item name="android:windowNoTitle">true</item>

</style>

</resources>

2、在需要的启动Activity里设置:

[Activity(Label = "我读报", MainLauncher = true, Theme = "@style/Theme.Splash", ScreenOrientation = Android.Content.PM.ScreenOrientation.Portrait, NoHistory = true)]

public class SplashActivity : Activity{

}

09
4

Mono for android中js与c#代码的交互

0
归档:2013年4月分类:开源Mono

移动互联网的开发包中有大量的功能是设计到显示网页的,有些甚至是直接调取远程的网页,主要依赖于WebView这个控件,而实际的开发过程中,我们需要在js代码中调用c#里面的代码,或者在c#代码里直接调用相关的js方法,以完成更好的交互效果。

android sdk提供了非常简便的办法来实现这一的功能,而Mono for android也提供了相关的方法,步骤如下:

step1:首先要在创建一个类,这个类是用于与js代码交互的,如下所示

public class Wodubao : Java.Lang.Object

{

Context context;

public Wodubao (Context context)

{

this.context = context;

}

public Wodubao (IntPtr handle, JniHandleOwnership transfer)

: base (handle, transfer)

{

}

[Export ("Article")]

// to become consistent with Java/JS interop convention, the argument cannot be System.String.

public void Article (Java.Lang.String articleid)

{

ArticleActivity currentArticle = (ArticleActivity)context;

currentArticle.Finish ();

Intent intent = new Intent (context, typeof(ArticleActivity));

intent.PutExtra ("articleid", articleid.ToString ());

context.StartActivity (intent);

}

}

说明:Wodubao是一个用于与js代码交互的类,在这个类里定义了一个方法Article ,这个就是js代码里的方法,方法需要一个参数 articleid,这个方法可以调用当前activity里的所有方法,以实现相应的效果。

step2:在初始化WebView的时候注册js方法,代码示例

WebView webView = new WebView (this);
webView.Settings.JavaScriptEnabled = true;
webView.AddJavascriptInterface (new Wodubao (this), "Wodubao");

注意:这里需要将JavaScriptEnabled的属性设置为true。

step3:代码中只要有Article的js方法,调用后就会执行C#代码里的方法,以完成交互效果。

02
4

Mono for android中MD5加密的方法

0
归档:2013年4月分类:开源Mono

其实和C#的代码是一样的,完全可以复用,这里给出相应的代码

/// <summary>
/// MD5
/// </summary>
/// <param name="strText"></param>
/// <returns></returns>
public string MD5Hash(string strText)
{
MD5 MD5 = new MD5CryptoServiceProvider();
byte[] datSource = encoding.GetBytes(strText);
byte[] newSource = MD5.ComputeHash(datSource);
string byte2String = null;
for (int i = 0; i < newSource.Length; i++)
{
string thisByte = newSource[i].ToString("x");
if (thisByte.Length == 1) thisByte = "0" + thisByte;
byte2String += thisByte;
}
return byte2String.ToUpper();
}

28
3

Mono for android中使用sqlite

0
归档:2013年3月分类:开源Mono

小型数据库的使用在移动开发过程中非常方便,Mono for android提供了多种数据库访问方式,可以使用sqlite、使用WCF直接访问数据库,sqlite的访问非常简单,下面是一个使用monodroid(或者Mono for andorid访问数据库的方法):

/// <summary>

/// A helper class for working with SQLite

/// </summary>

public static class Database

{

private static string db_file = "database.db3";

public static SqliteConnection GetConnection ()

{

var dbPath = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.Personal), db_file);

bool exists = File.Exists (dbPath);

if (!exists)

SqliteConnection.CreateFile (dbPath);

var conn = new SqliteConnection ("Data Source=" + dbPath);

if (!exists)

CreateDatabase (conn);

return conn;

}

private static void CreateDatabase (SqliteConnection connection)

{

var sql = "CREATE TABLE version (Id INTEGER PRIMARY KEY AUTOINCREMENT, isforce NUMERIC, version TEXT, url TEXT, info TEXT, dates datetime,isupdate NUMERIC);";

connection.Open ();

using (var cmd = connection.CreateCommand ()) {

cmd.CommandText = sql;

int temp=cmd.ExecuteNonQuery ();

}

connection.Close ();

}

}

具体的使用sql语句访问数据库的方法例子:

public List<Model.appVersion> GetAllVersion ()

{

List<Model.appVersion> mList=new List<Model.appVersion>();

var sql ="select id,isforce,version,url,info,dates,isupdate from version";

using (var conn = Database.GetConnection ()) {

conn.Open ();

using (var cmd = conn.CreateCommand ()) {

cmd.CommandText = sql;

using (var reader = cmd.ExecuteReader ()) {

while (reader.Read ())

mList.Add(new Model.appVersion(reader.GetInt32(0),reader.GetInt32(1),reader.GetString(2),reader.GetString(3),reader.GetString(4),reader.GetDateTime(5),reader.GetInt32(6)));

}

}

}

return mList;

}

29
1

Mono的早期历史

0
归档:2013年1月分类:开源Mono

Mono的早期历史

Miguel de Icaza  2003.10.13

Q:   你好,冒昧地问一下,是否在dotGnu of .NET 之前Mono项目就已经开始了?我很好奇。

我在那时候开始着手Mono项目的开发,对于Mono,事情大概是这样的:

2000年9月份,当.NET的文档出现的时候,我就开始对这个技术充满了兴趣,然后和所有人一样开始对字节码解释器进行研究,但是我面临一个问题:没有详细描述metadata的说明。

.NET的最终文档是在2001年1月22日的时候发布了,那段时间我开始写信给.NET的相关人员,希望能得到那份遗漏的关于metadata的文档。

我一边等待回复,一边开始开发自己的C#编译器,顺便当作第一个学习C#的练习工作,然后开始写解释器。

写编译器的这段时间,Rhys联系了我,他已经通过反编译获得了一些早期的metadata代码格式,这是一项非常有趣的工作,那时候我们小组只有三个人一起努力:Rhys、Saurik和我。

Sam Ruby发布了ECMA委员拥有的C#的二进制文档,虽然这并不是本来的安排。我并不知道事情会朝哪个方向发展,但是在2001年4月份,ECMA委员会发布了那份遗漏的文档。

这就意味着我自己的C#编译器可以完成解析器的工作了,然后我开始在周围让大家试用我的编译器,同时我们可以开始完整地学习文档,用于构建一个开源项目。

我们的研发工作包括:构建一个metadata读取器,这个工作人让我们很痛苦,因为Saurik已经做了一个了,他感觉他的代码没有被利用,而Rhys也有一个读取器,我个人并不是很喜欢(因为它不是基于Linux/Gnumeric代码风格)。

从2000年9月份开始,我就感叹.NET框架的魅力,当我们在Ximian内部讨论它的优点的时候,我们会跟其他人的工作联想起来,比如“Labs”组织的CORBA、SOAP和Perl团队为Gnome绑定基础服务(别忘记了:支撑我们工作的动力是我们希望我们的APIs只需要编写一次,就可以使用任何语言来调用)

“Labs”组织的努力工作最终结果是:Bonobo-conf,ORBit2, bonobo-activation, Soup, 和Perl/Gtk绑定,目的是希望创建工具提高我们的生产力:用更少的时间开发更多的应用,提升更高的抽象和标准在桌面应用上,以节省我们的时间和开发成本。

他们的产品是积极有效的,但是所有这些用.NET框架都可以轻易实现。

但是当我们完成学习的时候,我很清楚地知道是有可能去构建这样一种技术,他可以成为未来linux桌面的高效开发工具。请记住:从这个角度说,我们正在开发一个最大的桌面应用程序,随着时间的向前发展,最终都会开源(比如Mozilla和OpenOffice最开始也是收费产品,后面也变得开源了)。

虽然我们已经拥有在构建开源项目的经验,但还要处理一些相对重要的代码还是很痛苦。

Nat Friedman强力支持我们,希望我们的努力能获得更大的突破,我们获得了在Ximian实验室的管理权,大部分在Ximian实验室的开发人员都加入了Mono团队。我们团队的目标就是希望能创造出一个工具以提高开发人员的工作效率。

我们保持平静,让我们的团队慢慢迁移到Mono项目中,大家逐步收缩自己手头上的项目,仅仅有两位保留在原来的项目,最后,Dietmar, Paolo, Dick和我都开始为Mono项目工作。

Ravi马上就会加入我们,他会帮助我们开发C#编译器。

很显然,一个小团队是不可能开发出一个完整的.NET框架的替代品的,所以我计划把Mono变成一个开源的项目。负责市场推广的Jon Perr知道我们把项目推广出去。

我们原来计划在2001年7月19日公开发布,这样我们就可以赶上O'Reilly会议,Tim O'Reilly一直都很支持我们的项目,他从一开始就帮助Mono,当它还是一个很小项目的时候。当我们发布我们的项目的时候,我们同时发布了metadata框架、C#编译器和一些初始类库。

所以官方地说,Mono的发布日期是那天,但是它酝酿了很久。

对我来说,什么最重要并不是关键,因为Mono项目之于我意味着:一项帮助Linux在桌面获得成功的技术。当然,它有自己的生命发展周期,Mono并不是因为Ximain/Novell选择它所以才有它,对它的贡献和选择来自它的贡献者和选择者。所以,Mono要变得强大和壮大也要靠它的使用者。

希望这样能回答你的问题。

英文源地址 http://lists.ximian.com/pipermail/mono-list/2003-October/016345.html

公告栏

欢迎大家来到我的博客,我是dodoro,希望我的博客能给你带来帮助。