Android中如何处理其他应用程序的呼入

举例说明,“电话簿”里存有“路人甲”的个人信息,并记录着详细地址;点击该地址之后会自动跳转到"Google Map",并用详细地址关键字进行检索;概要的说,就是在“电话簿”里呼出"Google Map";本文将以1个Demo为例对该部分知识进行阐述。

一、效果图展示

android 4j-contacts-address-search-contacts-view    android 4j-contacts-address-search-contacts-onclick
android 4j-contacts-address-search-app-welcome    android 4j-contacts-address-search-app-searching

二、知识点

1. 通过配置"AndroidManifest.xml"监听该类Intent

首先,必须得知晓该操作所发出的Intent为何类别,包含哪些数据信息;有1个简单可行之法,就是在"DDMS"中查看该操作所输出的Log,例如:
04-22 04:57:55.854: I/ActivityManager(206): START {act=android.intent.action.VIEW dat=geo:0,0?q=上海市淮海中路775号 cmp=android/com.android.internal.app.ResolverActivity} from pid 8722

其次,通过抽象上文中的Log信息来配置"AndroidManifest.xml",进而达到监听该类Intent的效果,具体配置如下:

<activity
	android:name=".IntentReceiverActivity" >
	<intent-filter>
		<action android:name="android.intent.action.VIEW" />
		<category android:name="android.intent.category.DEFAULT" />
		<data android:scheme="geo" />
	</intent-filter>
</activity>

也就是说,利用"IntentReceiverActivity"来接受并处理该类Intent。加入该段代码之后,就能达到如下效果:应用出现在呼出应用程序列表中,即第2幅图所示。

2. 如何启动应用程序

只需在"IntentReceiverActivity"中加入如下代码即可:

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	startActivity(getPackageManager().getLaunchIntentForPackage(getPackageName()));
}

3. 存储地址关键字

在"IntentReceiverActivity"的onResume中做如下处理:

@Override
protected void onResume() {
	super.onResume();
	Common.setIsFromContactsFlag(true);
	Common.setAddress(getAddressFromIntent(getIntent()));
	finish();
}

4. 使用关键字进行检索

在"MainActivity"中做如下处理:

@Override
protected void onResume() {
	super.onResume();

	if (Common.getIsFromContactsFlag()) {
		String address = Common.getAddress();

		if ((address == null) || (address.length() < 1)) {
			showToast(R.string.main_address_invalid);
		} else {
			showProgressDialog(address);
		}

		Common.setAddress(null);
		Common.setIsFromContactsFlag(false);
	}
}

三、补充说明

1. "WelcomeActivity"和"MainActivity"之间的关联

程序启动时开启"WelcomeActivity",也就是说"WelcomeActivity"为"android.intent.category.LAUNCHER";在Welcome画面"Loaing..."数秒之后迁移到"MainActivity",即地址检索是在Main中进行。

2. 该部分代码不一定在所有手机上都适用

不同手机的“电话簿”中按下“详细地址”所发出的Intent信息不尽相同,不仅与AndroidSDK版本有关,而且还与手机型号有关,因为很多手机都是定制ROM;当前代码仅仅针对"Galaxy Nexus"而言。

3. 该工程在Eclipse中目录结构

android 4j-contacts-address-search-eclipse

四、源码下载

http://7xl53s.com1.z0.glb.clouddn.com/download/2015/08/src/4j-contacts-address-search.zip

Android中的类MVC设计方案 – Trigger机制

当然,“MVC”是针对Web项目提出的;也就是说,Android中没有MVC一说;但此处“MVC”能十分精辟地进行概括,毕竟Java开发人员对该概念十分之熟悉,所以在此借用“类MVC”;下面进入正题:

一、效果图展示

android 4j trigger     android 4j triggerandroid 4j trigger

层面是无法体现该方案的便宜之处,但从设计层面可以得到很好的体现,层次划分清晰可见,每层各负其责,耦合度相当之低。为了更能说明问题,4J就分别以ListActivity(即上图中的“4J NewsHeadline”)和Activity(即上图中的“4J Weather”)进行展示;但两者的实质完全相同,避免累赘,下文在阐述时仅以“4J NewsHeadline”为例。

二、设计思想

为了能更直观的阐述设计思想,先将类图和时序图贴出来:
android 4j trigger
android 4j trigger

1. OnTriggerListener

该Interface有且仅有1个方法onTrigger (),具体如下:

public boolean onTrigger(TriggerInfo triggerInfo);

2. FJUIControlManager

首先,该类中有3个成员属性:
mCurrentActivity:Activity,用于记录当前处于foreground状态的Activity;
mOnTriggerListener: OnTriggerListener,用于监听mCurrentActivity;
mFJUIControlManagerHandler: FJUIControlManagerHandler

其次,该类中有3个重要的成员方法:setCurrentActivity()、setOnTriggerListener()和postTrigger()。

该类的详细代码如下:

public class FJUIControlManager {

	// 当前处于foreground状态的Activity
	private static Activity mCurrentActivity;
	// 用于监听mCurrentActivity
	private static OnTriggerListener mOnTriggerListener;

	// 接收Control层post过来的Trigger,并通过重写handleMessage()做出相应处理
	private static final FJUIControlManagerHandler 
		mFJUIControlManagerHandler = new FJUIControlManagerHandler();

	public static void setCurrentActivity(Activity currentActivity) {
		mCurrentActivity = currentActivity;
	}

	public static void setOnTriggerListener(OnTriggerListener onTriggerListener) {
		mOnTriggerListener = onTriggerListener;
	}

	public static void removeOnTriggerListener() {
		mOnTriggerListener = null;
	}

	/**
	 * 供Control层调用,将Trigger post到主消息队列中去。
	 */
	public static void postTrigger(TriggerInfo triggerInfo) {
		Message msg = mFJUIControlManagerHandler.obtainMessage
                                                  (TriggerId.IDENTIFY, triggerInfo);
		mFJUIControlManagerHandler.sendMessage(msg);
	}

	private static class FJUIControlManagerHandler extends Handler {
		/**
		 * 注意:一定得是Looper.getMainLooper()
		 */
		public FJUIControlManagerHandler() {
			super(Looper.getMainLooper());
		}

		@Override
		public void handleMessage(Message msg) {
			// msg来自于postTrigger()
			if ((msg == null) || (msg.what != TriggerId.IDENTIFY) 
                             || (msg.obj == null) || (msg.obj.getClass() != TriggerInfo.class))
				return;

			TriggerInfo triggerInfo = (TriggerInfo) msg.obj;
			mOnTriggerListener.onTrigger(triggerInfo);
		}
	}

}

3. FJListActivity

该类主要负责重写onResume()、onPause()和实现onTrigger();在onResume()中主要负责给FJUIControlManager. mCurrentActivity赋值和注册监听,这样在子类中就不需每次重复,只需super.onResume()代替之;在onPause()中主要负责注销监听,同理在子类中只需super.onPause()代替之;而onTrigger()留给子类重写,进而分别实现各自的功能。该类的具体代码如下:

public class FJListActivity extends ListActivity implements OnTriggerListener {

	@Override
	protected void onResume() {
		super.onResume();

		FJUIControlManager.setCurrentActivity(this);
		FJUIControlManager.setOnTriggerListener(this);
	}

	@Override
	protected void onPause() {
		super.onPause();

		FJUIControlManager.removeOnTriggerListener();
	}

	public boolean onTrigger(TriggerInfo triggerInfo) {
		return true;
	}
}

4. FJTriggerMainActivity

该类继承FJListActivity,有1个重要的成员属性:mNewsHeadlineRequestId;2个重要的成员方法:onListItemClick()和onTrigger();具体代码(主要部分)如下:

public class FJTriggerMainActivity extends FJListActivity {

	// 发送NewsHeadline请求时返回的Trigger唯一标识符
	private int mNewsHeadlineRequestId; 

	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {		
		switch (position) {
		case 0:			
			// 将数据请求发送到Control层,返回一个Trigger唯一标识符。
			mNewsHeadlineRequestId = NewsHeadlineControl.requestHeadlines();
			break;
		default:
			break;
		}
	}

	@Override
	public boolean onTrigger(TriggerInfo triggerInfo) {
		int triggerId = triggerInfo.getId();

		if (triggerId == mNewsHeadlineRequestId) {
			switch (triggerInfo.getArg1()) {
			case TriggerId.NEWS_HEADLINE_SUCCESS:
                                // 画面跳转
				startActivity(new Intent(this, FJNewsHeadlineActivity.class));
				break;
			case TriggerId.NEWS_HEADLINE_SERVER_EXCEPTION:
				Toast.makeText(this, 
                                             R.string.news_headline_request_server_exception, 1000).show();
				break;
			default:
				break;
			}
		} else {}

		return true;
	}

}

5. NewsHeadlineControl

该类代码比较单一,不需过多解释,就直接贴代码:

public class NewsHeadlineControl extends FJControl {

	private static List mHeadlinesList = new ArrayList();

	public static int requestHeadlines() {
		// 从服务器获取数据
		getHeadlinesFromServer();

		TriggerInfo triggerInfo = TriggerInfo.factory
                                                        (TriggerId.NEWS_HEADLINE_IDENTIFY,
						         TriggerId.NEWS_HEADLINE_SUCCESS);

		// 将Trigger发送到消息队列中去
		FJUIControlManager.postTrigger(triggerInfo);

		return triggerInfo.getId();
	}

	public static List getHeadlines() {
		return mHeadlinesList;
	}

6. FJNewsHeadlineActivity

该类主要用于展示内容,而这些数据从Control层取得:NewsHeadlineControl.getHeadlines()

三、源码下载

http://7xl53s.com1.z0.glb.clouddn.com/download/2015/08/src/4jtrigger.zip

关于搭建Android App – APK推荐站点的一些想法

4J前期做过部分准备工作,并将该项目命名为“APK Talk”,下面将详细阐述其中的各个细节。

一、想法萌芽

前不久入手一部HTC Desire,本本分分地熟悉了一星期;实在是耐不住寂寞,开始折腾起来。首先,刷MIUI的ROM——当然,这个不是我要说的重点;然后,开始折腾App。

在此插播一段说明,4J个人习惯将Android App称为APK,可能有些许牵强,APK是Android Package的缩写,可能有点偏向于开发方面的知识。这种叫法主要有以下两种缘由:第一,Android App安装包的扩展名就为”.apk”。第二,出于搜索排名方面的考虑,如果以”android app”作为关键字进行Google,因为是组合查询,搜索结果中无效数据的比例应该非常大;毕竟当下iPhone已经自然而然地抢占”app”关键字,民众一听到”app”这三个字符就立马想到的是Apple的AppStore;但如果以”apk”作为关键字的话,无效数据比例应该非常之小。

回到正题。所谓智能机,最大的乐趣应该来源于折腾无穷无尽的App;但作为一名Android菜鸟,如何选取APK就是一件令人无比头疼的事情。当时4J就在想,如果有这么一个APK推荐站点该多让人省心。

二、市场需求

作为一个Android手机终端用户,对手机的功能需求就不仅仅只是局限于语音通话和文字短信;他们往往对功能的需求会高出许多,或者是对新功能充满好奇,等等;然而,功能的载体是APK;所以说随着Android手机用户数量的节节攀升,对APK的需求会日益增多;软件厂商为了满足用户的需求,进而达到抢占市场的目的,就会大量发布APK。

如此一来,菜场里就如雨后春笋,数以亿计的APK上架,最终导致终端用户不知如何取舍。作为一名折腾者,4J一般是通过如下几种途径来获取心仪的APK,具体如下:

1. 菜场排行榜

android market 排行榜

2. 搜索引擎

以下两幅截图分别对应“android app 推荐”和“android app 测评”关键字的搜索结果,呈现出一种十分发散的态势;反应出这两组关键字没有被特意推广,也就是说,APK推荐或测评站点少之又少。

android app 推荐

android app 测评

3. 文字推荐

例如某个博主或围脖主钟情于某一款APK,然后写篇日志对之进行阐述;但他们并不是专门从事APK推荐,这部分比例应该很小。

综上所述,APK推荐站点的市场需求还是非常之大,前景被4J所看好。

三、示例站点:Apps Ku

大体与Apps Ku类同,在细节方面可能有一定的差别。4J感觉Apps Ku可取之处就是关注点比较专一、切入点十分准确;但上面的文章内容过于简单,基本上在菜场的APK描述一栏就能获取得到,可读性有待深究。通过阅读上面的文章,读者只能获得该App的名字,而无法知晓是否是自己需要的,因为文章写的过于官方,省略掉核心的测评感言片段;从而得进行安装试玩;如此一来推荐站点的效果就大打折扣,发挥不到应有的效应。

4J当前有些许不成形的想法,例如,测评感言、对比测评、视频测评等。本想和Herock交流交流,向前辈取取经,但一直没能通过GTalk联系上。

四、站点定位

新站最大的忌讳就是将目标制定的过于雄伟、气派,这样到最后大多的结局就是项目周期一拖再拖,最后一事无成。毕竟人的精力有限,每个人的关注点比较局限、单一;当然如果运营方有足够的财力和人力的话,那就得另当别论。接下来,将详细阐述项目的进度和一些细节。

1. 项目定位

APK Talk定位于小众,关注点十分专一,唯一专注于Android App,即APK;不会去关注iOS App,也不会去关注Android资讯;以团队博客的形式进行展示。还是举例说明:某一天,4J发现一款名为”Shazam”的APK不错,可推荐性较强;4J就会针对该APK,结合自己的使用经历撰写一篇测评文章:首先,讲述功能;接着,表述自己的使用经历;然后,测评感言等等。

接下来,就是该项目的发稿频率;计划每周3-5篇文章——过少,用户等待时间过长,会失去耐性;过多,文章质量欠佳,毕竟可推荐性强的APK为数不多。

然后,就是项目的人员配置,3-5人,每人每周发布一篇文章即可,不宜超过两篇;主要是考虑到人的精力有限,吸引人眼球的APK同样稀少;在数亿计的APK中淘出一个心仪的对象谈何容易。

2. 项目进度

项目所需的域名、主机、Twitter帐号、Weibo帐号都已经布局完毕,粘贴于下:

6月1日之前,我会独自将该项目开展起来;后期再拉人入伙,共同努力。

五、盈利模式

现阶段没去考虑盈利模式,只是觉得这项目可行性很高;当然,也不太可能有实际的盈利;但在其他方面可能会得到一些回报;例如,会结识一波具共同癖好的折腾者;可能会让撰稿者在“行内”有一定的知名度;4J将此理解成人脉,可以为以后做事提供便捷。

多说两句,人脉在成事中可说举足轻重;古语有云:天时、地利、人和。就拿iPad导航来说,该站点的idea和具体的实现应该可以算得上so easy,况且iPad也是个非常之小众的群体,但该站点能生存下来,并且健康状况还算OK——4J的猜测,具体每天多少访问量不得而知;其中起着决定性因素的就应该归结于我爱水煮鱼等人的人脉。举这个例子只是为了说明人脉的重要性,并没有其他神马更深层次的用意,不要想太多;如果该站站长觉得内容欠妥的话,可以联系4J来将之删除。

简而言之,可以通过之来为撰稿者积累人脉,这也是目前唯一可能的“获利”。

六、投资成本

投资成本主要分为两部分;第一,经济成本;第二,时间成本。初期的经济成本基本上可以忽略,域名续费和主机续费;因为初期的访问量不可能大,一般的共享主机都能吃消。反倒,时间成本占据一个可怕的比重,要发布可读性强的APK测评文章,撰稿者必须花足够多的时间去试用大量的APK,然后从中进行筛选,这方面的代价可是巨大的。

七、存在问题

最大的问题就是欠缺人手,目前有强烈意向的唯独我一人。尝试着去拉人入伙,可终究没能成功;只好在此广发英雄帖。目前还需2-4人,一定是要对该idea认可的,且具有强烈意愿的,千万别抱着试一试的态度;因为这是一个持久战,且没有任何物资回报。

如果有意愿者,可通过以下方式联系4J>> http://about.me/vincent4j

4JPlayer.Ver1.1-软件评测

一、欢迎界面

双击app图标之后,首先显示的是欢迎界面(如下左图所示),该界面上含有1张静态图片和1个动态点状进度条;当进度条循环完2轮之后,跳转到程序主界面中的Local Tab(如下右图所示)。
4JPlayer 欢迎界面 welcome  4JPlayer Play Tab 播放页签

二、初始化界面

上右图展示的是初始化时Local Tab的界面,该界面罗列出SDCard上的音频文件。接下来展示该状态下Play Tab(如下左图所示)和Remote Tab界面(如下右图所示);该状态下Remote Tab罗列出服务器上的音频文件。

4JPlayer 初始化PlayTab界面  4JPlayer 初始化RemoteTab界面

三、音乐播放界面

当用户点击Local Tab中某一首歌曲,例如选择标题一的右图中“Vincent.mp3”时;传来歌曲声音,该歌曲后多出一个播放按钮(如下左图所示);音乐播放一段时间之后,将界面切换到Play Tab,该界面中的数字计时器以1s为单位进行增加,进度条也随之向前挪动,中间的控制键显示的是暂停图标(如下右图所示)。
4JPlayer 播放时Local Tab界面  4JPlayer 播放时Play Tab界面

四、音乐暂停界面

继续播放一段时间后,点击Play Tab中的暂停按钮,音乐停止播放,数字计时器停止,滚动条停止,中间的控制键变更成播放图标(如下左图所示)。切换到Local Tab,此时“Vincent.mp3”后面显示为暂停图标(如下右图所示)。一段时间之后,点击“Vincent.mp3”,传出音乐,变成播放图标;切换到Play Tab,数字计时器和滚动条都动起来。
4JPlayer 暂停时Play Tab界面  4JPlayer 暂停时Local Tab界面

五、音乐切换界面

在标题四的基础之上,点击“下一首”,传来“Nobody”歌声,数字计时器和滚动条从零开始变化。此时切换到Local Tab,“Nobody.mp3”后面显示一个播放图标。

在上文的基础上,点击“Secret.mp3”,Secret音乐传出,该列后面出现播放图标。切换到Play Tab,此时展示着Secret的播放进度。

六、下载Mp3

切换到Remote Tab,点击“Hero.mp3”后面的下载图标,弹出下载提示(如下左图所示);一段时间之后浏览sdcard\mp3路径,发现“Hero.mp3”文件。
4JPlayer Download mp3 下载mp3  4JPlayer mp3 notify

七、Notification

当退出Activity时,Status Bar里出现个播放图标和文字“4JPlayer”,滑开,如上右图所示。

八、总结

1. 不足之处

  • 拖动播放功能未实现
  • 歌词同步功能未实现
  • 界面布局过于简单

2. 可行之处

  • 基本功能已实现
  • 通过该demo进一步学习Android SDK

九、APK和源码下载

http://7xl53s.com1.z0.glb.clouddn.com/download/2015/08/src/4jplayer-1.1.zip