10

基本上我想要做的是通过一个意图将一个自定义的可打包对象传递给 RemoteViewsService,从而传递给我的 RemoteViewsFactory。出于某种原因,这根本不起作用:S 每当我尝试这样做时,小部件最终都会显示“问题加载小部件”文本。

当我尝试相同的事情时,我没有将其传递给 RemoteViewsService,而是将其传递给常规 Activity,它完全按预期工作。

我试图在网上找到我的答案,但我没有成功,因此我现在在这里发帖希望得到帮助。

我一直试图让它在我的主程序中工作一段时间。但我就是想不通。所以我试着把它归结起来,看看我是否在某个时候做错了什么。我成功地重现了问题,我重现问题的基础来自 CommonsGuy 的 LoremWidget ( https://github.com/commonsguy/cw-advandroid/tree/master/AppWidget/LoremWidget ) 和一个随机的可打包示例 ( http ://prasanta-paul.blogspot.dk/2010/06/android-parcelable-example.htm l) 我已经修改以显示我的问题。(希望我不会遇到麻烦,在这两个链接上使用了代码)

这是上传到随机文件主机上的完整代码,以防有人想测试我在说什么: http ://www.filedropper.com/remoteviewserviceparcelerrorexample

所以总结一下我的问题:

为什么我不能将我的可打包对象(单独或包装在 ArrayList 中)传递给我的 RemoteViewsService?(当相同的代码适用于 Activity 时)

我真的希望有人能够帮助我。现在在我的主程序中我序列化到内部存储,然后几乎立即从 RemoteViewsService 再次反序列化它,从我读过的所有内容来看,这不是很有效!

编辑:刚刚记住,由于某种原因,在我的主程序中,如果我传递了一个自定义对象,其中 ArrayList 和 Strings 设置为 null,并且布尔值全部为 false(基本上正是对象在创建时的样子),则小部件看起来正常(即没有“问题加载小部件”消息)。

编辑:在查看了外观(未过滤到我正在运行的应用程序)之后,我现在看到了一些错误(我想我最好学会在没有任何文件的情况下查看所有未过滤的内容:)):

     11-13 17:14:27.268: D/AndroidRuntime(8840): >>>>>> AndroidRuntime START com.android.internal.os.RuntimeInit <<<<<<
    11-13 17:14:27.268: D/AndroidRuntime(8840): CheckJNI is ON
    11-13 17:14:27.340: D/AndroidRuntime(8840): Calling main entry com.android.commands.pm.Pm
    11-13 17:14:27.348: W/ActivityManager(90): No content provider found for permission revoke: file:///data/local/tmp/com.commonsware.android.appwidget.lorem.LoremActivity.apk
    11-13 17:14:27.348: W/ActivityManager(90): No content provider found for permission revoke: file:///data/local/tmp/com.commonsware.android.appwidget.lorem.LoremActivity.apk
    11-13 17:14:27.356: I/PackageManager(90): Removing non-system package:com.commonsware.android.appwidget.lorem
    11-13 17:14:27.360: I/ActivityManager(90): Force stopping package com.commonsware.android.appwidget.lorem uid=10034
    11-13 17:14:27.360: I/ActivityManager(90): Killing proc 8798:com.commonsware.android.appwidget.lorem/10034: force stop
    11-13 17:14:27.400: D/dalvikvm(90): GC_CONCURRENT freed 511K, 17% free 8611K/10311K, paused 0ms+0ms
    11-13 17:14:27.400: I/PackageManager(90): Package com.commonsware.android.appwidget.lorem codePath changed from /data/app/com.commonsware.android.appwidget.lorem-2.apk to /data/app/com.commonsware.android.appwidget.lorem-1.apk; Retaining data and using new
    11-13 17:14:27.404: I/PackageManager(90): Running dexopt on: com.commonsware.android.appwidget.lorem
    11-13 17:14:27.440: D/dalvikvm(8850): DexOpt: load 12ms, verify+opt 4ms
    11-13 17:14:27.448: W/PackageManager(90): Code path for pkg : com.commonsware.android.appwidget.lorem changing from /data/app/com.commonsware.android.appwidget.lorem-2.apk to /data/app/com.commonsware.android.appwidget.lorem-1.apk
    11-13 17:14:27.448: W/PackageManager(90): Resource path for pkg : com.commonsware.android.appwidget.lorem changing from /data/app/com.commonsware.android.appwidget.lorem-2.apk to /data/app/com.commonsware.android.appwidget.lorem-1.apk
    11-13 17:14:27.452: I/ActivityManager(90): Force stopping package com.commonsware.android.appwidget.lorem uid=10034
    11-13 17:14:27.460: D/PackageManager(90): New package installed in /data/app/com.commonsware.android.appwidget.lorem-1.apk
    11-13 17:14:27.472: I/ActivityManager(90): Force stopping package com.commonsware.android.appwidget.lorem uid=10034
    11-13 17:14:27.496: D/dalvikvm(266): GC_EXPLICIT freed 127K, 9% free 6766K/7367K, paused 0ms+0ms
    11-13 17:14:27.512: D/dalvikvm(221): GC_EXPLICIT freed 878K, 57% free 15010K/34119K, paused 0ms+0ms
    11-13 17:14:27.584: D/dalvikvm(90): GC_EXPLICIT freed 385K, 18% free 8558K/10311K, paused 0ms+0ms
    11-13 17:14:27.588: D/PackageManager(90): generateServicesMap(android.accounts.AccountAuthenticator): 2 services unchanged
    11-13 17:14:27.620: D/PackageManager(90): generateServicesMap(android.content.SyncAdapter): 4 services unchanged
    11-13 17:14:27.620: D/BackupManagerService(90): Received broadcast Intent { act=android.intent.action.PACKAGE_REMOVED dat=package:com.commonsware.android.appwidget.lorem flg=0x10000010 (has extras) }
    11-13 17:14:27.620: D/PackageManager(90): generateServicesMap(android.accounts.AccountAuthenticator): 2 services unchanged
    11-13 17:14:27.620: D/PackageManager(90): generateServicesMap(android.content.SyncAdapter): 4 services unchanged
    11-13 17:14:27.628: W/ResourceType(90): Failure getting entry for 0x7f060000 (t=5 e=0) in package 0 (error -75)
    11-13 17:14:27.632: D/BackupManagerService(90): Received broadcast Intent { act=android.intent.action.PACKAGE_ADDED dat=package:com.commonsware.android.appwidget.lorem flg=0x10000010 (has extras) }
    11-13 17:14:27.636: V/BackupManagerService(90): updatePackageParticipantsLocked: #1
    11-13 17:14:27.640: W/RecognitionManagerService(90): no available voice recognition services found
    11-13 17:14:27.652: D/dalvikvm(8854): Not late-enabling CheckJNI (already on)
    11-13 17:14:27.684: I/ActivityManager(90): Start proc com.commonsware.android.appwidget.lorem for broadcast com.commonsware.android.appwidget.lorem/.WidgetProvider: pid=8854 uid=10034 gids={}
    11-13 17:14:27.688: D/BackupManagerService(90): Received broadcast Intent { act=android.intent.action.PACKAGE_REPLACED dat=package:com.commonsware.android.appwidget.lorem flg=0x10000010 (has extras) }
    11-13 17:14:27.688: V/BackupManagerService(90): updatePackageParticipantsLocked: #1
    11-13 17:14:27.740: I/dalvikvm(8854): Turning on JNI app bug workarounds for target SDK version 11...
    11-13 17:14:27.756: D/dalvikvm(90): GC_EXPLICIT freed 409K, 16% free 8687K/10311K, paused 0ms+4ms
    11-13 17:14:27.792: D/AndroidRuntime(8840): Shutting down VM
    11-13 17:14:27.796: D/dalvikvm(8840): GC_CONCURRENT freed 99K, 79% free 447K/2048K, paused 0ms+0ms
    11-13 17:14:27.796: D/dalvikvm(8840): Debugger has detached; object registry had 1 entries
    11-13 17:14:27.812: I/AndroidRuntime(8840): NOTE: attach of thread 'Binder Thread #3' failed
    11-13 17:14:27.820: D/WidgetProvider(8854): ParcelData=ParcelData [id=0, name=null, desc=null, cities=[suwon, delhi]]
    11-13 17:14:27.820: D/WidgetProvider(8854): ArrayList<ParcelData>=[ParcelData [id=0, name=null, desc=null, cities=[suwon, delhi]]]
    11-13 17:14:27.824: V/ParcelData(8854): writeToParcel...0
    11-13 17:14:27.824: V/ParcelData(8854): writeToParcel...0
    11-13 17:14:27.828: V/ParcelData(8854): writeToParcel...0
    11-13 17:14:27.828: V/ParcelData(8854): writeToParcel...0
    11-13 17:14:27.828: E/Parcel(221): Class not found when unmarshalling: com.commonsware.android.appwidget.lorem.ParcelData, e: java.lang.ClassNotFoundException: com.commonsware.android.appwidget.lorem.ParcelData
    11-13 17:14:27.832: W/AppWidgetHostView(221): updateAppWidget couldn't find any view, using error view
    11-13 17:14:27.832: W/AppWidgetHostView(221): android.os.BadParcelableException: ClassNotFoundException when unmarshalling: com.commonsware.android.appwidget.lorem.ParcelData
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at android.os.Parcel.readParcelable(Parcel.java:1966)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at android.os.Parcel.readValue(Parcel.java:1854)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at android.os.Parcel.readListInternal(Parcel.java:2103)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at android.os.Parcel.readArrayList(Parcel.java:1544)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at android.os.Parcel.readValue(Parcel.java:1875)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at android.os.Parcel.readMapInternal(Parcel.java:2094)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at android.os.Bundle.unparcel(Bundle.java:223)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at android.os.Bundle.putInt(Bundle.java:436)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at android.content.Intent.putExtra(Intent.java:4695)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at android.widget.RemoteViews$SetRemoteViewsAdapterIntent.apply(RemoteViews.java:401)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at android.widget.RemoteViews.performApply(RemoteViews.java:1606)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at android.widget.RemoteViews.apply(RemoteViews.java:1583)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at android.appwidget.AppWidgetHostView.updateAppWidget(AppWidgetHostView.java:289)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at android.appwidget.AppWidgetHost.updateAppWidgetView(AppWidgetHost.java:283)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at android.appwidget.AppWidgetHost$UpdateHandler.handleMessage(AppWidgetHost.java:84)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at android.os.Handler.dispatchMessage(Handler.java:99)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at android.os.Looper.loop(Looper.java:137)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at android.app.ActivityThread.main(ActivityThread.java:4424)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at java.lang.reflect.Method.invokeNative(Native Method)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at java.lang.reflect.Method.invoke(Method.java:511)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    11-13 17:14:27.832: W/AppWidgetHostView(221):   at dalvik.system.NativeStart.main(Native Method)
    11-13 17:14:28.116: D/AndroidRuntime(8872): >>>>>> AndroidRuntime START com.android.internal.os.RuntimeInit <<<<<<
    11-13 17:14:28.116: D/AndroidRuntime(8872): CheckJNI is ON
    11-13 17:14:28.200: D/AndroidRuntime(8872): Calling main entry com.android.commands.am.Am
    11-13 17:14:28.204: I/ActivityManager(90): START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.commonsware.android.appwidget.lorem/.LoremActivity} from pid 8872
    11-13 17:14:28.208: W/WindowManager(90): Failure taking screenshot for (192x135) to layer 21020
    11-13 17:14:28.220: W/NetworkManagementSocketTagger(90): setKernelCountSet(10034, 1) failed with errno -2
    11-13 17:14:28.240: D/AndroidRuntime(8872): Shutting down VM
    11-13 17:14:28.244: D/dalvikvm(8872): GC_CONCURRENT freed 100K, 77% free 475K/2048K, paused 4ms+0ms
    11-13 17:14:28.244: D/dalvikvm(8872): Debugger has detached; object registry had 1 entries
    11-13 17:14:28.244: I/AndroidRuntime(8872): NOTE: attach of thread 'Binder Thread #1' failed
    11-13 17:14:28.252: W/InputManagerService(90): Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@b38c3ef0
    11-13 17:14:28.504: W/NetworkManagementSocketTagger(90): setKernelCountSet(10034, 0) failed with errno -2
4

5 回答 5

3

我最终做了 TreKing 在这里谈论的事情: https ://groups.google.com/d/msg/android-developers/KX0BUAbOTKY/jqW_ZokCH3gJ

我所做的是创建一个“Bundleable”接口,它基本上完成了 Parcelable 的意图。扩展此接口的对象可以放置自己并从 Bundle 对象重新创建自己,该对象本身是 Parcelable,因此您可以像您的对象一样发送它 - 除了系统总是知道如何加载 Bundle 类型因此您不知道的小事实不会遇到这个错误。

并按照他的代码示例:

public interface Bundleable
{
 public Bundle toBundle();

 public void fromBundle(Bundle b);
}

public class MyClass implements Bundleable
{
 public Bundle toBundle()
 { 
  Bundle b = new Bundle();
  // Fill b with data
  return b;
 }

 public void from Bundle(Bundle b)
 {
  // set properties from data in b
 }
}

// ...

MyClass m = new MyClass();
Intent i = new Intent();
i.putBundleExtra("MyClass", m.toBundle());

// ... Elsewhere

Bundle b = intent.getBundleExtra("MyClass");
MyClass m = new MyClass(b); // Constructor calls fromBundle(b);

就像我从一开始就期望整个包裹交易一样工作!:)

于 2012-11-14T18:55:43.043 回答
3

我对 Serializable 对象 ArrayList 也有同样的问题。当我尝试像这样在 AppWidgetManager 中传递列表时

Intent listIntent = new Intent(context, WidgetService.class);
listIntent.putExtra("list", myList);

它只是没有用。但是将相同的数据放在一个包中,然后将其放入意图中作为额外的工作。

Intent listIntent = new Intent(context, WidgetService.class);
Bundle extrasBundle = new Bundle();
extrasBundle.putSerializable("list", myList);
listIntent.putExtra("bundle", extrasBundle);

我在这里找到了一篇关于堆栈溢出的帖子,其中用户解释了将额外内容直接放入或捆绑在一起的 区别:在 Android 中使用 Bundle 而不是直接 Intent putExtra() 的优势 看起来它有效,因为只有在你将额外内容放入时一个捆绑包,可以通过多个意图传递它。

于 2018-03-24T12:21:57.377 回答
0

如果您无法使用Parcelable. 而是通过ParcelDataas a String。只需将您的writeToParcel()andParcelData(Parcel source)方法转换为这样的东西(穷人的“序列化”):

public String serializeToString() {
    StringBuilder sb = new StringBuilder();
    sb.append(Integer.toString(id)).append('|').append(name).append('|').append(desc)
        .append('|');
    for (String c : cities) {
        sb.append(c).append(';');
    }
    sb.append('|');
    return sb.toString();
}

ParcelData(String source) {
    String[] parts = source.split("|");
    id = Integer.parseInt(parts[0]);
    name = parts[1];
    desc = parts[2];
    cc = parts[3].split(";");
    if (cc.length == 0) {
        cities = new String[0]; // No cities
    } else {
        cities = new String[cc.length - 1]; // Last element is empty
        for (int i = 0; i < cc.length - 1; i++) {
            cities[i] = cc[i];
        }
    }
}

我没有通过编译器运行它,所以它可能有愚蠢的语法错误。你应该明白了。

于 2012-11-13T18:16:16.870 回答
0

我知道为时已晚,我的意思是为时已晚,但今天我遇到了同样的问题,并找到了一个最少代码行的解决方案。决定与解决方案分享。Gson因此,基本上您可以使用Google的 API 将任何对象(甚至是对象列表)转换为字符串。看看这个:

ComplextObject object=new ComplexObject();
Type type = new TypeToken<ComplextObject>() {}.getType();
intent.putExtra("key",convertToJsonString(object,type)); //that's it

或者在“另一边”阅读这个对象:

String jsonString=intent.getStringExtra("key");
Type type = new TypeToken<ComplexObject>() {}.getType();
ComplexObject object=convertFromJsonString(jsonString,type);

这里是convertToJsonStringconvertFromJsonString方法:

public static <T> T convertFromJsonString(String jsonString, Type type){
    if(jsonString==null) return null;
    Gson gson=new Gson();
    return gson.fromJson(jsonString,type);
}

public static String convertToJsonString(Object object, Type type){
    if(object==null) return null;
    Gson gson=new Gson();
    return gson.toJson(object,type);
}
于 2017-06-03T00:23:19.593 回答
0

这是使用 Kotlin 和 Bundle 的示例代码:

在你updateAppWidget()

val intent = Intent(context, ItemsCollectionRemoteViewsService::class.java)
            .apply {
                val extrasBundle = Bundle()
                extrasBundle.putSerializable(WIDGET_DATA, myCustomData)
                putExtra(WIDGET_BUNDLE, extrasBundle)
            }
        remoteViews.setRemoteAdapter(R.id.items_list_view, intent)

然后在RemoteViewsService.RemoteViewsFactory

override fun onCreate() {
    val bundleData = data?.getBundleExtra(WIDGET_BUNDLE)
    bundleData?.let {
        val myCustomData = bundleData.getSerializable(WIDGET_DATA) as MyCustomData?
        myCustomData?.let {
            list = myCustomData.myList
        }
    }
}
于 2022-01-25T17:24:32.767 回答