android 一个应用去获取另一个应用assets下面的资源通过框架代码桥梁------项目实战成功案例
来源:互联网 发布:python mac 编辑:程序博客网 时间:2024/04/27 21:33
最终效果
HelloWord工程应用代码:
package com.pateo;import android.app.Activity;import android.os.Bundle;import android.widget.TextView;import com.pateo.R;import android.content.pm.PackageManager;public class HelloWordActivity extends Activity {TextView tv ; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); tv = (TextView)findViewById(R.id.tv); PackageManager pm = getPackageManager(); try{ tv.setText("result : " + pm.getAppVoiceEntryInfo("packageName", "xmlName", "bnfName").speechContent); }catch( android.content.pm.PackageManager.NameNotFoundException e){ tv.setText("" + e); } }}上面getAppVoiceEntryInfo不是PackageManager自带的方法是我自己添加的方法
我是自己写了个HelloWord工程,放入到源码中,自己的应用怎么放入框架中要遵循:修改/bulid/target/product/generic.mk 把工程编译到系统中
generic.mk## Copyright (C) 2007 The Android Open Source Project## Licensed under the Apache License, Version 2.0 (the "License");# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.## This is a generic product that isn't specialized for a specific device.# It includes the base Android platform.PRODUCT_PACKAGES := \ AccountAndSyncSettings \ CarHome \ DeskClock \ AlarmProvider \ Bluetooth \ Calculator \ Calendar \ Camera \ CertInstaller \ DrmProvider \ Email \ Gallery3D \ LatinIME \ Launcher2 \ Mms \ Music \ Provision \ Protips \ QuickSearchBox \ Settings \ Sync \ Updater \ CalendarProvider \ SyncProvider \ Helloworld
HelloWord的Android.mk文件
LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE_TAGS := optionalLOCAL_SRC_FILES := $(call all-java-files-under, src)LOCAL_PACKAGE_NAME := HelloWordLOCAL_CERTIFICATE := platforminclude $(BUILD_PACKAGE)# Use the folloing include to make our test apk.include $(call all-makefiles-under,$(LOCAL_PATH))
把HelloWord工程放入package/apps/目录下面,在此工程的assets木下建立一个xml文件里面写一些内容,我在这里建的文件名:voice_recognition.xml
到这里基本应用的代码完成了
下面是框架中的一些实现步骤
Ctrl+Shift+T [Eclipse的快捷键方式,下同]搜索类:PackageManager为其添加如下代码:
/** * 语音识别获取应用的识别词条的动作的启动信息 * @param packageName 应用的包名 * @param xmlName 词条对应的动作定义的文件 * @param bnfName 词条识别的入科大库的文件 * @return * @throws NameNotFoundException */ public abstract AppVoiceEntryInfo getAppVoiceEntryInfo(String packageName, String xmlName,String bnfName)throws NameNotFoundException;PackageManager是个抽象类,我们F4找到它的实现类之一:MockPackageManager为其添加如下代码:
@Overridepublic AppVoiceEntryInfo getAppVoiceEntryInfo(String packageName,String xmlName, String bnfName) throws NameNotFoundException {// TODO Auto-generated method stub throw new UnsupportedOperationException();}找到PackageManager的实现类之二:MockPackageManager为其添加如下代码:
@Overridepublic AppVoiceEntryInfo getAppVoiceEntryInfo(String packageName,String xmlName, String bnfName) throws NameNotFoundException {try {AppVoiceEntryInfo appVoiceEntryInfo = mPM.getAppVoiceEntryInfo("packageName", "xmlName", "bnfName");Log.d(TAG,"============================getAppVoiceEntryInfo====================================");return appVoiceEntryInfo;} catch (RemoteException e) {throw new RuntimeException("Package manager has died", e);}}上面的mPM的定义:
private final IPackageManager mPM;
它是怎么被赋值的呢Ctril+F找“mPM = ”,找到如下赋值的地方:
ApplicationPackageManager(ContextImpl context, IPackageManager pm) {mContext = context;mPM = pm;}
通过Ctril+Shift+G找到ApplicationPackageManager(ContextImpl context, IPackageManager pm)这个构造方式是在哪被调用的即初始化的
@Overridepublic PackageManager getPackageManager() {if (mPackageManager != null) {return mPackageManager;}IPackageManager pm = ActivityThread.getPackageManager();if (pm != null) {// Doesn't matter if we make more than one instance.return (mPackageManager = new ApplicationPackageManager(this, pm));}return null;}
接着找pm是怎么来的,点击getPackageManager()这个方法,进入ActivityThread有关这个方法的实现,代码如下:
public static IPackageManager getPackageManager() { if (sPackageManager != null) { //Slog.v("PackageManager", "returning cur default = " + sPackageManager); return sPackageManager; } IBinder b = ServiceManager.getService("package"); //Slog.v("PackageManager", "default service binder = " + b); sPackageManager = IPackageManager.Stub.asInterface(b); //Slog.v("PackageManager", "default service = " + sPackageManager); return sPackageManager; }
从上面我们可以知道了,我们需要找到IPackageManager.aidl文件,通过Ctril+H找到这个aidl文件,当然你也可以在Ubuntu下通过grep过滤来找到这个aidl文件,个人习惯不同
这个aidl文件中加一个 AppVoiceEntryInfo getAppVoiceEntryInfo(String packageName, String xmlName, String bnfName);接口方法
/***** Copyright 2007, The Android Open Source Project**** Licensed under the Apache License, Version 2.0 (the "License");** you may not use this file except in compliance with the License.** You may obtain a copy of the License at**** http://www.apache.org/licenses/LICENSE-2.0**** Unless required by applicable law or agreed to in writing, software** distributed under the License is distributed on an "AS IS" BASIS,** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.** See the License for the specific language governing permissions and** limitations under the License.*/package android.content.pm;import android.content.ComponentName;import android.content.Intent;import android.content.IntentFilter;import android.content.pm.ActivityInfo;import android.content.pm.ApplicationInfo;import android.content.pm.FeatureInfo;import android.content.pm.IPackageInstallObserver;import android.content.pm.IPackageDeleteObserver;import android.content.pm.IPackageDataObserver;import android.content.pm.IPackageMoveObserver;import android.content.pm.IPackageStatsObserver;import android.content.pm.InstrumentationInfo;import android.content.pm.PackageInfo;import android.content.pm.ProviderInfo;import android.content.pm.PermissionGroupInfo;import android.content.pm.PermissionInfo;import android.content.pm.ResolveInfo;import android.content.pm.ServiceInfo;import android.net.Uri;import android.content.IntentSender;import android.content.pm.AppVoiceEntryInfo;/** * See {@link PackageManager} for documentation on most of the APIs * here. * * {@hide} */interface IPackageManager { AppVoiceEntryInfo getAppVoiceEntryInfo(String packageName, String xmlName, String bnfName); PackageInfo getPackageInfo(String packageName, int flags); int getPackageUid(String packageName); int[] getPackageGids(String packageName); String[] currentToCanonicalPackageNames(in String[] names); String[] canonicalToCurrentPackageNames(in String[] names); PermissionInfo getPermissionInfo(String name, int flags); List<PermissionInfo> queryPermissionsByGroup(String group, int flags); PermissionGroupInfo getPermissionGroupInfo(String name, int flags); List<PermissionGroupInfo> getAllPermissionGroups(int flags); ApplicationInfo getApplicationInfo(String packageName, int flags); ActivityInfo getActivityInfo(in ComponentName className, int flags); ActivityInfo getReceiverInfo(in ComponentName className, int flags); ServiceInfo getServiceInfo(in ComponentName className, int flags); int checkPermission(String permName, String pkgName); int checkUidPermission(String permName, int uid); boolean addPermission(in PermissionInfo info); void removePermission(String name); boolean isProtectedBroadcast(String actionName); int checkSignatures(String pkg1, String pkg2); int checkUidSignatures(int uid1, int uid2); String[] getPackagesForUid(int uid); String getNameForUid(int uid); int getUidForSharedUser(String sharedUserName); ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags); List<ResolveInfo> queryIntentActivities(in Intent intent, String resolvedType, int flags); List<ResolveInfo> queryIntentActivityOptions( in ComponentName caller, in Intent[] specifics, in String[] specificTypes, in Intent intent, String resolvedType, int flags); List<ResolveInfo> queryIntentReceivers(in Intent intent, String resolvedType, int flags); ResolveInfo resolveService(in Intent intent, String resolvedType, int flags); List<ResolveInfo> queryIntentServices(in Intent intent, String resolvedType, int flags); List<PackageInfo> getInstalledPackages(int flags); List<ApplicationInfo> getInstalledApplications(int flags); /** * Retrieve all applications that are marked as persistent. * * @return A List<applicationInfo> containing one entry for each persistent * application. */ List<ApplicationInfo> getPersistentApplications(int flags); ProviderInfo resolveContentProvider(String name, int flags); /** * Retrieve sync information for all content providers. * * @param outNames Filled in with a list of the root names of the content * providers that can sync. * @param outInfo Filled in with a list of the ProviderInfo for each * name in 'outNames'. */ void querySyncProviders(inout List<String> outNames, inout List<ProviderInfo> outInfo); List<ProviderInfo> queryContentProviders( String processName, int uid, int flags); InstrumentationInfo getInstrumentationInfo( in ComponentName className, int flags); List<InstrumentationInfo> queryInstrumentation( String targetPackage, int flags); /** * Install a package. * * @param packageURI The location of the package file to install. * @param observer a callback to use to notify when the package installation in finished. * @param flags - possible values: {@link #FORWARD_LOCK_PACKAGE}, * {@link #REPLACE_EXISITING_PACKAGE} * @param installerPackageName Optional package name of the application that is performing the * installation. This identifies which market the package came from. */ void installPackage(in Uri packageURI, IPackageInstallObserver observer, int flags, in String installerPackageName); void finishPackageInstall(int token); /** * Delete a package. * * @param packageName The fully qualified name of the package to delete. * @param observer a callback to use to notify when the package deletion in finished. * @param flags - possible values: {@link #DONT_DELETE_DATA} */ void deletePackage(in String packageName, IPackageDeleteObserver observer, int flags); String getInstallerPackageName(in String packageName); void addPackageToPreferred(String packageName); void removePackageFromPreferred(String packageName); List<PackageInfo> getPreferredPackages(int flags); void addPreferredActivity(in IntentFilter filter, int match, in ComponentName[] set, in ComponentName activity); void replacePreferredActivity(in IntentFilter filter, int match, in ComponentName[] set, in ComponentName activity); void clearPackagePreferredActivities(String packageName); int getPreferredActivities(out List<IntentFilter> outFilters, out List<ComponentName> outActivities, String packageName); /** * As per {@link android.content.pm.PackageManager#setComponentEnabledSetting}. */ void setComponentEnabledSetting(in ComponentName componentName, in int newState, in int flags); /** * As per {@link android.content.pm.PackageManager#getComponentEnabledSetting}. */ int getComponentEnabledSetting(in ComponentName componentName); /** * As per {@link android.content.pm.PackageManager#setApplicationEnabledSetting}. */ void setApplicationEnabledSetting(in String packageName, in int newState, int flags); /** * As per {@link android.content.pm.PackageManager#getApplicationEnabledSetting}. */ int getApplicationEnabledSetting(in String packageName); /** * Free storage by deleting LRU sorted list of cache files across * all applications. If the currently available free storage * on the device is greater than or equal to the requested * free storage, no cache files are cleared. If the currently * available storage on the device is less than the requested * free storage, some or all of the cache files across * all applications are deleted (based on last accessed time) * to increase the free storage space on the device to * the requested value. There is no guarantee that clearing all * the cache files from all applications will clear up * enough storage to achieve the desired value. * @param freeStorageSize The number of bytes of storage to be * freed by the system. Say if freeStorageSize is XX, * and the current free storage is YY, * if XX is less than YY, just return. if not free XX-YY number * of bytes if possible. * @param observer call back used to notify when * the operation is completed */ void freeStorageAndNotify(in long freeStorageSize, IPackageDataObserver observer); /** * Free storage by deleting LRU sorted list of cache files across * all applications. If the currently available free storage * on the device is greater than or equal to the requested * free storage, no cache files are cleared. If the currently * available storage on the device is less than the requested * free storage, some or all of the cache files across * all applications are deleted (based on last accessed time) * to increase the free storage space on the device to * the requested value. There is no guarantee that clearing all * the cache files from all applications will clear up * enough storage to achieve the desired value. * @param freeStorageSize The number of bytes of storage to be * freed by the system. Say if freeStorageSize is XX, * and the current free storage is YY, * if XX is less than YY, just return. if not free XX-YY number * of bytes if possible. * @param pi IntentSender call back used to * notify when the operation is completed.May be null * to indicate that no call back is desired. */ void freeStorage(in long freeStorageSize, in IntentSender pi); /** * Delete all the cache files in an applications cache directory * @param packageName The package name of the application whose cache * files need to be deleted * @param observer a callback used to notify when the deletion is finished. */ void deleteApplicationCacheFiles(in String packageName, IPackageDataObserver observer); /** * Clear the user data directory of an application. * @param packageName The package name of the application whose cache * files need to be deleted * @param observer a callback used to notify when the operation is completed. */ void clearApplicationUserData(in String packageName, IPackageDataObserver observer); /** * Get package statistics including the code, data and cache size for * an already installed package * @param packageName The package name of the application * @param observer a callback to use to notify when the asynchronous * retrieval of information is complete. */ void getPackageSizeInfo(in String packageName, IPackageStatsObserver observer); /** * Get a list of shared libraries that are available on the * system. */ String[] getSystemSharedLibraryNames(); /** * Get a list of features that are available on the * system. */ FeatureInfo[] getSystemAvailableFeatures(); boolean hasSystemFeature(String name); void enterSafeMode(); boolean isSafeMode(); void systemReady(); boolean hasSystemUidErrors(); /** * Ask the package manager to perform dex-opt (if needed) on the given * package, if it already hasn't done mode. Only does this if running * in the special development "no pre-dexopt" mode. */ boolean performDexOpt(String packageName); /** * Update status of external media on the package manager to scan and * install packages installed on the external media. Like say the * MountService uses this to call into the package manager to update * status of sdcard. */ void updateExternalMediaStatus(boolean mounted, boolean reportStatus); String nextPackageToClean(String lastPackage); void movePackage(String packageName, IPackageMoveObserver observer, int flags); boolean addPermissionAsync(in PermissionInfo info); boolean setInstallLocation(int loc); int getInstallLocation();}
由哪个类来实现上面这个框架方法呢?我通过找关键字IPackageManager.Stub找到了class PackageManagerService extends IPackageManager.Stub,下面我们就需要来实现这个抽象方法了:
public AppVoiceEntryInfo getAppVoiceEntryInfo(String packageName, String xmlName,String bnfName){ AppVoiceEntryInfo appVoiceEntryInfo = new AppVoiceEntryInfo(); appVoiceEntryInfo.speechContent = voiceContent; Log.d(TAG,"getAppVoiceEntryInfo method appVoiceEntryInfo.speechContent : " + appVoiceEntryInfo.speechContent); return appVoiceEntryInfo; }
先看实体类
package android.content.pm;import java.util.HashMap;import android.os.Parcel;import android.os.Parcelable;public class AppVoiceEntryInfo implements Parcelable {public String packageName;public String activityName;public String serviceName;public String xmlName;public String bnfName;public String entry;public String uri;public String recognitionType;public String speechContent;public String action;public HashMap<String, String> map = new HashMap<String, String>();public int describeContents() {// TODO Auto-generated method stubreturn 0;}public void writeToParcel(Parcel dest, int flags) {// TODO Auto-generated method stubdest.writeMap(map);dest.writeString(packageName);dest.writeString(activityName);dest.writeString(xmlName);dest.writeString(bnfName);dest.writeString(entry);dest.writeString(uri);dest.writeString(recognitionType);dest.writeString(speechContent);dest.writeString(action);}public static final Parcelable.Creator<AppVoiceEntryInfo> CREATOR = new Parcelable.Creator<AppVoiceEntryInfo>() {public AppVoiceEntryInfo createFromParcel(Parcel source) {return new AppVoiceEntryInfo(source);}public AppVoiceEntryInfo[] newArray(int size) {return new AppVoiceEntryInfo[size];}};private AppVoiceEntryInfo(Parcel source){packageName = source.readString();activityName = source.readString();xmlName = source.readString();bnfName = source.readString();entry = source.readString();uri = source.readString();recognitionType = source.readString();speechContent = source.readString();action = source.readString();map = source.readHashMap(HashMap.class.getClassLoader()); }public AppVoiceEntryInfo() {// TODO Auto-generated constructor stub}}
public static String voiceContent = null;
这个变量的赋值:
private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanMode) { mLastScanError = PackageManager.INSTALL_SUCCEEDED; String scanPath = scanFile.getPath(); parseFlags |= mDefParseFlags; PackageParser pp = new PackageParser(scanPath); pp.setSeparateProcesses(mSeparateProcesses); final PackageParser.Package pkg = pp.parsePackage(scanFile, scanPath, mMetrics, parseFlags); voiceContent = pp.voiceContent; Log.d(TAG,"Voice Contect : " + voiceContent);
上面pp.voiceContent;的值是怎么来的呢?接着看PackageParser中的实现:
public static String voiceContent = null; public String convertStreamToString(InputStream is) { /* * To convert the InputStream to String we use the BufferedReader.readLine() * method. We iterate until the BufferedReader return null which means * there's no more data to read. Each line will appended to a StringBuilder * and returned as String. */ BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sb.append(line + "\n"); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); } public Package parsePackage(File sourceFile, String destCodePath, DisplayMetrics metrics, int flags) { mParseError = PackageManager.INSTALL_SUCCEEDED; mArchiveSourcePath = sourceFile.getPath(); if (!sourceFile.isFile()) { Log.w(TAG, "Skipping dir: " + mArchiveSourcePath); mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK; return null; } if (!isPackageFilename(sourceFile.getName()) && (flags&PARSE_MUST_BE_APK) != 0) { if ((flags&PARSE_IS_SYSTEM) == 0) { // We expect to have non-.apk files in the system dir, // so don't warn about them. Log.w(TAG, "Skipping non-package file: " + mArchiveSourcePath); } mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK; return null; } if ((flags&PARSE_CHATTY) != 0 && Config.LOGD) Log.d( TAG, "Scanning package: " + mArchiveSourcePath); XmlResourceParser parser = null; AssetManager assmgr = null; InputStream inputStream = null; boolean assetError = true; try { assmgr = new AssetManager(); int cookie = assmgr.addAssetPath(mArchiveSourcePath); if(cookie != 0) { Log.d(TAG, "sourceFile : " + sourceFile + " destCodePath : " + destCodePath + " flags : " + flags + " cookie : " + cookie + " ArchiveSourcePath : " + mArchiveSourcePath); parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml"); try{ inputStream = assmgr.open("voice_recognition.xml"); }catch(Exception e){ Log.d(TAG,"" + e); } if(inputStream != null){ Log.d(TAG,"============================= success ==========================" ); voiceContent = convertStreamToString(inputStream); Log.d(TAG,"Voice Contect : " + voiceContent); }
看到上面你应该都明白了吧,呵呵,我也该睡觉了明天还要上班,我电脑太慢, 在Eclipse里面每写个东西就卡死要等一会,上面是个Demo只是为了说明意思,代码不值钱,值钱的是想法,想法哪里来靠看源码啊。
有关过程中的停顿
Checking API: checkapi-lastChecking API: checkapi-current(unknown): error 3: Added class AppVoiceEntryInfo to package android.content.pm(unknown): error 4: Added public method android.content.pm.PackageManager.getAppVoiceEntryInfo******************************You have tried to change the API from what has been previously approved.To make these errors go away, you have two choices: 1) You can add "@hide" javadoc comments to the methods, etc. listed in the errors above. 2) You can update current.xml by executing the following command: make update-api To submit the revised current.xml to the main Android repository, you will need approval.******************************make: *** [out/target/common/obj/PACKAGING/checkapi-current-timestamp] 错误 38
上面提示当你修改了框架代码你更改了api需要执行命令#make update-api
- android 一个应用去获取另一个应用assets下面的资源通过框架代码桥梁------项目实战成功案例
- android应用Assets目录下的资源
- android得到assets下面的资源
- android大杂烩--一个应用如何读取另一个apk中的资源
- android一个应用的activity调用另一个应用的activity
- android项目中如何获取assets下面的文件在SD卡上面的保存路径
- android获取assets资源
- Android 一个应用启动另一个应用的说明
- android读写assets目录下面的资源文件(文件夹)
- Android读写assets目录下面的资源文件(文件夹)
- android读写assets目录下面的资源文件(文件夹)
- Android读写assets目录下面的资源文件(文件夹)
- Android学习之拷贝assets文件夹下面的资源
- Android读写assets目录下面的资源文件(文件夹)
- android一个应用吊起另一个应用
- Android 从一个应用打开另一个应用
- maven项目下面的一个dom4j的简单应用
- Android开发---Vitamio框架的实战应用
- Serializable 作用
- 2011年度最佳 jQuery 插件发布
- Node.js 0.6.5 稳定版发布
- Guid-Globally Unique Identifier
- 60 个激发你灵感的电子商务网站展示
- android 一个应用去获取另一个应用assets下面的资源通过框架代码桥梁------项目实战成功案例
- 给你的网站添加地图频道 .
- 模仿Google日程的小控件
- 扩展EXT时间控件,可以选择到时分秒
- Web地图工具收集---Google Map/51Map/mapabc/mapbar API
- 使用ajax技术无刷新动态调用股票信息
- 终于找到关闭IE时清理Session的方法了
- 【水晶玻璃鞋 8】端口映射
- K&R C Exercise 2-7 Solution