Android 需要数据获取的小部件仅显示正在加载
Android widget that requires data fetching only shows loading
我正在尝试通过 android 小部件选择器在视图中添加一个小部件。一个简单的模拟时钟小部件显示正确,但必须获取数据的小部件仅显示加载而不显示数据,如下面的屏幕截图所示。
我的小部件创建代码是从 Hosting Android Widget 完成的。
我的代码是:
class MainActivity : AppCompatActivity() {
private lateinit var mAppWidgetManager: AppWidgetManager
lateinit var mAppWidgetHost: AppWidgetHost
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mAppWidgetManager = AppWidgetManager.getInstance(this)
mAppWidgetHost = AppWidgetHost(this, APPWIDGET_HOST_ID)
add_widget.setOnClickListener {
selectWidget()
}
}
fun selectWidget() {
val appWidgetId = mAppWidgetHost.allocateAppWidgetId()
val pickIntent = Intent(AppWidgetManager.ACTION_APPWIDGET_PICK)
pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
addEmptyData(pickIntent)
startActivityForResult(pickIntent, REQUEST_PICK_APPWIDGET)
}
private fun addEmptyData(pickIntent: Intent) {
val customInfo = arrayListOf<Parcelable>()
pickIntent.putParcelableArrayListExtra(AppWidgetManager.EXTRA_CUSTOM_INFO, customInfo)
val customExtras = arrayListOf<Parcelable>()
pickIntent.putParcelableArrayListExtra(AppWidgetManager.EXTRA_CUSTOM_EXTRAS, customExtras)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK) {
if (requestCode == REQUEST_PICK_APPWIDGET) {
configureWidget(data)
} else if (requestCode == REQUEST_CREATE_APPWIDGET) {
createWidget(data)
}
} else if (resultCode == RESULT_CANCELED && data != null) {
val appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
if (appWidgetId != -1) {
mAppWidgetHost.deleteAppWidgetId(appWidgetId)
}
}
}
private fun configureWidget(data: Intent?) {
val extras = data?.extras ?: return
val appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
val appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId)
if (appWidgetInfo.configure != null) {
val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE)
intent.component = appWidgetInfo.configure
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
startActivityForResult(intent, REQUEST_CREATE_APPWIDGET)
} else {
createWidget(data)
}
}
private fun createWidget(data: Intent?) {
val extras = data?.extras ?: return;
val appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
val appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
val hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
remove_widget.setOnClickListener {
removeWidget(hostView)
}
hostView.setAppWidget(appWidgetId, appWidgetInfo);
widgetLayout.addView(hostView);
}
override fun onStart() {
super.onStart()
mAppWidgetHost.startListening()
}
override fun onStop() {
super.onStop()
mAppWidgetHost.stopListening()
}
private fun removeWidget(hostView: AppWidgetHostView) {
mAppWidgetHost.deleteAppWidgetId(hostView.appWidgetId)
widgetLayout.removeView(hostView);
}
companion object {
const val REQUEST_PICK_APPWIDGET = 9
const val REQUEST_REFRESH_APPWIDGET = 10
const val APPWIDGET_HOST_ID = 442
const val REQUEST_CREATE_APPWIDGET = 5
}
}
这里,remove_widget和add_widget是按钮,widgetLayout是线性布局,用来添加widget。
编辑:
添加 gmail 小部件后,日志中显示以下错误。
2019-11-28 14:18:33.652 15363-15363/com.example.testapplication W/AppWidgetHostView: Error inflating RemoteViews : android.widget.RemoteViews$ActionException: android.widget.RemoteViews$ActionException: view: androidx.appcompat.widget.AppCompatImageView can't use method with RemoteViews: setImageResource(int)
注意:从另一个启动器,小部件按预期呈现,而不是从我的代码。另外,我用 applicationContext 改变了我的上下文。但是,它产生相同的结果。
如果您使用的是 androidX AppCompactActivity,请尝试使用普通 activity 看看是否可行。
import android.app.Activity;
//other codes....
public class MainActivity extends Activity {
// other codes...
}
** RemoteViews 仅限于支持以下布局:
- AdapterViewFlipper
- 框架布局
- 网格布局
- 网格视图
- 线性布局
- 列表视图
- 相对布局
- 堆栈视图
- ViewFlipper
** 以及以下小部件:
- 模拟时钟
- 按钮
- 时计
- 图片按钮
- ImageView
- 进度条
- 文本时钟
- TextView
** 不支持这些 类 的后代。
您应该检查您的布局!
我正在尝试通过 android 小部件选择器在视图中添加一个小部件。一个简单的模拟时钟小部件显示正确,但必须获取数据的小部件仅显示加载而不显示数据,如下面的屏幕截图所示。
我的小部件创建代码是从 Hosting Android Widget 完成的。
我的代码是:
class MainActivity : AppCompatActivity() {
private lateinit var mAppWidgetManager: AppWidgetManager
lateinit var mAppWidgetHost: AppWidgetHost
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mAppWidgetManager = AppWidgetManager.getInstance(this)
mAppWidgetHost = AppWidgetHost(this, APPWIDGET_HOST_ID)
add_widget.setOnClickListener {
selectWidget()
}
}
fun selectWidget() {
val appWidgetId = mAppWidgetHost.allocateAppWidgetId()
val pickIntent = Intent(AppWidgetManager.ACTION_APPWIDGET_PICK)
pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
addEmptyData(pickIntent)
startActivityForResult(pickIntent, REQUEST_PICK_APPWIDGET)
}
private fun addEmptyData(pickIntent: Intent) {
val customInfo = arrayListOf<Parcelable>()
pickIntent.putParcelableArrayListExtra(AppWidgetManager.EXTRA_CUSTOM_INFO, customInfo)
val customExtras = arrayListOf<Parcelable>()
pickIntent.putParcelableArrayListExtra(AppWidgetManager.EXTRA_CUSTOM_EXTRAS, customExtras)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK) {
if (requestCode == REQUEST_PICK_APPWIDGET) {
configureWidget(data)
} else if (requestCode == REQUEST_CREATE_APPWIDGET) {
createWidget(data)
}
} else if (resultCode == RESULT_CANCELED && data != null) {
val appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
if (appWidgetId != -1) {
mAppWidgetHost.deleteAppWidgetId(appWidgetId)
}
}
}
private fun configureWidget(data: Intent?) {
val extras = data?.extras ?: return
val appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
val appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId)
if (appWidgetInfo.configure != null) {
val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE)
intent.component = appWidgetInfo.configure
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
startActivityForResult(intent, REQUEST_CREATE_APPWIDGET)
} else {
createWidget(data)
}
}
private fun createWidget(data: Intent?) {
val extras = data?.extras ?: return;
val appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
val appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
val hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
remove_widget.setOnClickListener {
removeWidget(hostView)
}
hostView.setAppWidget(appWidgetId, appWidgetInfo);
widgetLayout.addView(hostView);
}
override fun onStart() {
super.onStart()
mAppWidgetHost.startListening()
}
override fun onStop() {
super.onStop()
mAppWidgetHost.stopListening()
}
private fun removeWidget(hostView: AppWidgetHostView) {
mAppWidgetHost.deleteAppWidgetId(hostView.appWidgetId)
widgetLayout.removeView(hostView);
}
companion object {
const val REQUEST_PICK_APPWIDGET = 9
const val REQUEST_REFRESH_APPWIDGET = 10
const val APPWIDGET_HOST_ID = 442
const val REQUEST_CREATE_APPWIDGET = 5
}
}
这里,remove_widget和add_widget是按钮,widgetLayout是线性布局,用来添加widget。
编辑: 添加 gmail 小部件后,日志中显示以下错误。
2019-11-28 14:18:33.652 15363-15363/com.example.testapplication W/AppWidgetHostView: Error inflating RemoteViews : android.widget.RemoteViews$ActionException: android.widget.RemoteViews$ActionException: view: androidx.appcompat.widget.AppCompatImageView can't use method with RemoteViews: setImageResource(int)
注意:从另一个启动器,小部件按预期呈现,而不是从我的代码。另外,我用 applicationContext 改变了我的上下文。但是,它产生相同的结果。
如果您使用的是 androidX AppCompactActivity,请尝试使用普通 activity 看看是否可行。
import android.app.Activity;
//other codes....
public class MainActivity extends Activity {
// other codes...
}
** RemoteViews 仅限于支持以下布局:
- AdapterViewFlipper
- 框架布局
- 网格布局
- 网格视图
- 线性布局
- 列表视图
- 相对布局
- 堆栈视图
- ViewFlipper
** 以及以下小部件:
- 模拟时钟
- 按钮
- 时计
- 图片按钮
- ImageView
- 进度条
- 文本时钟
- TextView
** 不支持这些 类 的后代。
您应该检查您的布局!