欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

详解Android Activity之间切换传递数据的方法

程序员文章站 2024-02-29 15:29:58
前面照着android系统的裁剪图片的功能自己写了一个相似的工具。功能是大体上实现了,但留下了一个调用的问题:如何从我的程序调用这个裁剪工具,并且获得裁剪后的图片呢?...

前面照着android系统的裁剪图片的功能自己写了一个相似的工具。功能是大体上实现了,但留下了一个调用的问题:如何从我的程序调用这个裁剪工具,并且获得裁剪后的图片呢?

其实这个也很简单了,就是intent的基础用法。

先上个图(界面依旧没优化,难看就难看吧):

起始activity,打开图片选择窗口,随便选择一张图片

详解Android Activity之间切换传递数据的方法

下面是跳转到裁剪界面

按下crop按钮,退出activity,回到原来界面,并显示裁剪后的图

详解Android Activity之间切换传递数据的方法

流程就是这样,也算模拟了系统裁剪功能的整体过程。下面就是实现功能的关键代码和说明了。

这里先称主程序为a,调用的子程序为b。

b是自己写的程序,调用他就需要定制自己的activity action。系统的action都对应一个action字符串,比如在intent类中定义的一些action常量:

public static final string action_main = "android.intent.action.main";
public static final string action_view = "android.intent.action.view";
public static final string action_edit = "android.intent.action.edit";
public static final string action_call = "android.intent.action.call";
public static final string action_call_emergency = "android.intent.action.call_emergency"; 

intent的构造方法中,会有一些如:intent.setclass(activity.this, x.class);的方法。但我不太喜欢这种方式。
除此之外常用的构造方法就是

public intent(string action);
public intent(string action, uri uri);

使用string,uri这种参数类型的intent对象称为隐式intent对象,即,通过intent类的构造方法并未指定intent的目标是哪一个activity,这些目标要依靠在androidmanifest.xml文件中的配置信息才能确定。也就是说,action所指的目标可能不止一个,或者说再androidmanifest.xml文件中可以配置多个接收同一个action的activity action。

在androidmanifest.xml中一般文件格式如下:

<application
android:allowbackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/apptheme" >
<activity
android:name="com.example.crop_image_my.mainactivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.main" />
<category android:name="android.intent.category.launcher" />
</intent-filter>
</activity>
</application> 

其中<action>标签指定一个系统定义的activity action。该action表示在应用程序启动时第一个启动的activity需要接收这个action。也就是说这个动作是android应用程序启动主窗口的动作。

因为需要自己的action启动裁剪程序,所以我在上面的xml中另外加了下面一段:

<intent-filter>
   <action android:name="com.example.crop_image_my.copper" />
<data android:scheme="crop" />
<category android:name="android.intent.category.default" />
</intent-filter> 

保留.main是我需要程序单独运行也可以(不知道删掉的话会怎样,没测试)

上面<data>标签定义一个scheme,所以后面的uri可以写作 crop://something

哦对,上面的是b的配置文件,a要启动b嘛。

下面在a中就可以调用b的intent了:

private void startmycropintent(string path) throws filenotfoundexception {
intent intent = new intent("com.example.crop_image_my.copper", uri.parse("crop://" + path));
startactivityforresult(intent, );
} 

上面构造intent就不说了,参数是前面配置文件里的。要想启动新的activity,使用startactivity()就可以,但为了能获取到返回值,就要用startactivityforresult()方法,在onactivityresult()进行处理。

第二个参数12是请求代码,对应onactivityresult(int requestcode,int resultcode, intent data)中第一个参数。这个数字可以随便写,但建议用资源写,比如某个按钮触发startactivityforresult(),就可以把这个按钮的r.id.button1当请求码(其实用什么都行了,只要方便识别)。

好,启动activity后,注意参数有一个uri,这个uri就是我选择的图片的路径,在裁剪的方法b中里要获取这个uri:

if (getintent().getdata() != null) {
imgpath = getintent().getdata().getpath(); // 参见uri的组成形式资料
log.v("<dbw>", imgpath);
mycropview.setbmppath(imgpath);
} 

写在oncreate里,在构造的时候就取得这个值并使用。

下面是关闭activity。在b里面写。直接放代码吧

@override
public void onclick(view v) {
// todo auto-generated method stub
switch (v.getid()) {
case r.id.btn_crop:
bitmap croppedimage = mycropview.getcroppedimage();
croppedimageview.setimagebitmap(croppedimage);
savecroppedimage(croppedimage);
// return to the last activity
log.v("<dbw>", newfilepath);
getintent().putextra("newpath", newfilepath);
setresult(, getintent());
break;
case r.id.btn_cancel:
setresult();
break;
default:
break;
}
finish();
} 

裁剪之后先保存图片,然后通过getintent().putextra()方法把图片路径存在intent里。“newpath”是随便起的名,作为取数据的标识。finish()是关闭这个activity。参数20是onactivityresult(int requestcode,int resultcode, intent data)的第二个参数。

最后获取截到的图片,在a写:

@override
protected void onactivityresult(int requestcode, int resultcode, intent data) {
super.onactivityresult(requestcode, resultcode, data);
switch (requestcode) {
case :
if (resultcode == ) {
string path = data.getextras().getstring("newpath");
log.v("<dbw>", "get------" + path);
bitmap bmp = bitmapfactory.decodefile(path);
iv.setimagebitmap(bmp);
} else if (resultcode == ) {
toast toast = toast.maketext(this, "您取消了操作", toast.length_long);
toast.show();
}
break;
default:
break;
}
} 

switch是针对不同的activity(当前只启动一个,标识码是12)。再对不同的resultcode做不同处理。

前面用了putextra设置数据,这里就用data.getextra方法获取bundle对象,在根据需要用getxxx方法获得不同的数据。

就是这么个过程。

4.28.2015

另一个简单方法:

同一个项目里建2个activity,eclipse 项目右击->new->others->android->android activity

manifest.xml:

<application
android:allowbackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/apptheme" >
<activity   启动显示的
android:name=".mainactivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.main" />
<category android:name="android.intent.category.launcher" />
</intent-filter>
</activity>
<activity                        切换的
android:name=".showmessage"
android:label="@string/title_activity_display_message"
android:parentactivityname=".mainactivity" >
<meta-data
android:name="android.support.parent_activity"
android:value="com.example.android_switchactivity.mainactivity" />
</activity>
</application> 

在mainactivity中添加:

public final static string extra_message = "com.example.android_switchactivity.message"; 这个string可以任意赋值,但要保证唯一intent intent = new intent(this, showmessage.class);
edittext met = (edittext)findviewbyid(r.id.edit_message);
string message = met.gettext().tostring();
intent.putextra(extra_message, message);
startactivity(intent); 

在第2个activity添加:

intent intent = getintent();
string message = intent.getstringextra(mainactivity.extra_message);
textview mtv = new textview(this);
mtv.settextsize(40);
mtv.settext(message);