首页 > 其他分享 >Android之Widget  Frame…

Android之Widget  Frame…

时间:2023-07-28 17:34:27浏览次数:34  
标签:widget Context App Widget context Android Frame android


       



2 AppWidget Framework



2.1 定义



       



(1)AppWidgetService是框架的的核心类,是系统 service之一,它负责widgets的管理工作。加载,删除,定时事件等都需要AppWidgetService的处理。开机自启动的。



         



(2)AppWidgetManager 负责widget视图的实际更新以及相关管理。






2.2 AppWidget Framework的大致流程



1. 编写一个widget(先不考虑后台服务以及用户管理界面等)
      实际是写一个事件监听类即一个BroadcastReceiver子类,当然框架已经提供了一个辅助类AppWidgetProvider,实现的类只要实现其方法即可,其中必须实现的方法是onUpdate ,其实就是一个定时事件,widget监听此事件
      另外就是规划好视图(layout),将此widget打包安装。
2. 当android系统启动时,AppWidgetService 就将负责检查所有的安装包,将检查
      AndroidManifest.xml(不要告诉我不知道,如果不知道可要看看基本开发知识了) 
      文件中有<metadata android:name="android.appwidget.provider" android:resource="@xml/appwidget_info" />
     



3. 从用户菜单将已经安装的widget添加到桌面,也就是将widget在桌面上显示出来,这个应该是由AppWidgetService和 AppWidgetManager完成的,其中AppWidgetManager 将负责将视图发送到桌面显示出来,并将此widget记录到系统文件中
4. AppWidgetService将根据widget配置中的updatePeriodMillis属性来定时发送 ACTION_APPWIDGET_UPDATE事件,此事件将激活widget的事件监听方法onUpdate,此方法将通过 AppWidgetManager完成widget内容的更新和其他操作。



3 AppWidgetHost



        AppWidgetHost 是实际控制widget的地方,大家注意,widget不是一个单独的用户界面程序,他必须寄生在某个程序(activity)中,这样如果程序要支持 widget寄生就要实现AppWidgetHost,桌面程序(Launcher)就实现了这个接口。

       



o 监听来自AppWidgetService的事件。



o 另外一个功能就是创建AppWidgetHostView。



         



Host的实现者



       



        LauncherAppWidgetHostVie w扩展了AppWidgetHostView,实现了对长按事件的处理。



        LauncherAppWidgetHost扩展了AppWidgetHost,这里只是重载了onCreateView,创建LauncherAppWidgetHostVie w的实例。



4 AppWidgetHostView

    

5 AppWidgetProvider

      


1 
    public 
    void  
    onUpdate(Context context, AppWidgetManager appWidgetManager, 
    int [] appWidgetIds)
    
2 
    public 
    void  
    onDeleted(Context context, 
    int [] appWidgetIds)
    
3 
    public 
    void  
    onEnabled(Context context)
    
4 
    public 
    void  
    onDisabled(Context context)


这几个函数用来响应AppWidgetService发出的相应的广播消息。

AppWidgetProvider的实现者



         


1 
  void  
  onUpdate(Context context, AppWidgetManager appWidgetManager, 
  int


onUpdate的实现基本上遵循下面的流程:



o 创建RemoteViews
o 调用AppWidgetManager的updateAppWidget去更新widget.



6 RemoteViews



          RemoteViews并不是一个真正的View,它没有实现View的接口,而只是一个用于描述View的实体。



          现在我们可以看出,Android中的AppWidget与google widget和中移动的widget并不是一个概念, 这里的AppWidget只是把一个进程的控件嵌入到别外一个进程的窗口里的一种方法。




组成部分






1 AppWidgetProviderInfo



          描述一个App Widget,如App Widget的布局, 更新频率



    一个App Widget的基本属性是通过AppWidgetProviderInfo去定义的,例如它的最小尺寸的布局,它的初始layout,多久更新App Widget   appwidget_provider.xml文件:


<?xml version="1.0" encoding="utf-8" 
  
<!-- Copyright (C) 2006 The Android
 
  
Licensed under the Apache
 
  
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.
 
  
-->
 
  
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
 
  
android:minWidth="60dp"
 
  
android:minHeight="30dp"
 
  
android:updatePeriodMillis="86400000"
 
  
android:initialLayout="@layout/appwidget_provider"
 
  
android:configure="com.example.android.apis.appwidget.ExampleAppWidgetConfigure"
 
  
>
 
  
</appwidget-provider
 
  <!-- 86400000 is the value of AlarmManager.INTERVAL_DAY - or once per day. -->

          configure 属性是当用户添加一个App Widget前启动的Activity,这个Activity的作用就是配置App Widget的属性。(Optional)



          updatePeriodMillis 属性定义了App Widget应该多久向AppWidgetProvider请求更新。实际更新的时间未必能保证及时更新,并且建议尽量不要频繁更新---比如一小时一次去更新电量。也可以容许用户去自定义更新的时间。






重大消息!!! SDK1.5之后此方法android:updatePeriodMillis就失效了



2 AppWidgetProvider



   AppWidgetProvider是BroadcastReceiver的子类,这个类处理App Widget广播。AppWidgetProvider只接收于App Widget有关系的广播,比如App Widget在updated, deleted, enabled, and disabled。当这些广播发生的时候,AppWidgetProvider会调用一下回调方法:


onUpdate(Context, AppWidgetManager, int[])
    间隔调用此方法去更新App Widget,间隔时间的设置是在AppWidgetProviderInfo下的updatePeriodMillis属性,同样当用户添加App Widget的时候也被调用。如果你已经声明了一个configuration Activity,用户添加App Widget的时候就不会调用onUpdate,但是在随后的更新中依然会被调用。

onDeleted(Context, int[])
    当App Widget 从App Widget host 中删除的时候调用。

onEnabled(Context)
    当App Widget第一次创建的时候调用。比如,当用户增加两个同样的App Widget时候,这个方法只在第一次去调用。如果你需要打开一个新的数据库或者其他的设置,而这在所有的App Widgets只需要设置一次的情况下,这个是最好的地方去实现它们。

onDisabled(Context)
    当App Widget的最后一个实例从App Widget host中被删除的时候调用。这里可以做一些在onEnabled(Context)中相反的操作,比如删除临时数据库。

onReceive(Context, Intent)
    每一个广播的产生都会调用此方法,而且是在上面方法之前被调用。通常不需要实现此方法。

   

   ApiDemo中的例子,ExampleAppWidgetProvider.java文件


package com.example.android.apis.appwidget;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.SystemClock;
import android.util.Log;
import android.widget.RemoteViews;
// Need the following import to get access to the app resources, since this
// class is in a sub-package.
import com.example.android.apis.R;

public class ExampleAppWidgetProviderextends AppWidgetProvider {
// log tag
private static final String TAG = "ExampleAppWidgetProvider" ;
 @Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int [] appWidgetIds) {
 Log.d(TAG, "onUpdate" );
// For each widget that needs an update, get the text that we should display:
// - Create a RemoteViews object for it
// - Set the text in the RemoteViews object
// - Tell the AppWidgetManager to show that views object for the widget.
final int N = appWidgetIds.length;
for (int i= 0 ; i< N; i++ ) {
int appWidgetId = appWidgetIds[i];
 String titlePrefix = ExampleAppWidgetConfigure.loadTitlePref(context, appWidgetId);
 updateAppWidget(context, appWidgetManager, appWidgetId, titlePrefix);
 }
 }
 @Override
public void onDeleted(Context context, int [] appWidgetIds) {
 Log.d(TAG, "onDeleted" );
// When the user deletes the widget, delete the preference associated with it.
final int N = appWidgetIds.length;
for (int i= 0 ; i< N; i++ ) {
 ExampleAppWidgetConfigure.deleteTitlePref(context, appWidgetIds[i]);
 }
 }
 @Override
public void onEnabled(Context context) {
 Log.d(TAG, "onEnabled" );
// When the first widget is created, register for the TIMEZONE_CHANGED and TIME_CHANGED
// broadcasts. We don't want to be listening for these if nobody has our widget active.
// This setting is sticky across reboots, but that doesn't matter, because this will
// be called after boot if there is a widget instance for this provider.
 PackageManager pm = context.getPackageManager();
 pm.setComponentEnabledSetting(
new ComponentName("com.example.android.apis" , ".appwidget.ExampleBroadcastReceiver" ),
 PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
 PackageManager.DONT_KILL_APP);
 }
 @Override
public void onDisabled(Context context) {
// When the first widget is created, stop listening for the TIMEZONE_CHANGED and
// TIME_CHANGED broadcasts.
 Log.d(TAG, "onDisabled" );
 PackageManager pm = context.getPackageManager();
 pm.setComponentEnabledSetting(
new ComponentName("com.example.android.apis" , ".appwidget.ExampleBroadcastReceiver" ),
 PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
 PackageManager.DONT_KILL_APP);
 }
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId, String titlePrefix) {
 Log.d(TAG, "updateAppWidget appWidgetId=" + appWidgetId + " titlePrefix=" + titlePrefix);
// Getting the string this way allows the string to be localized. The format
// string is filled in using java.util.Formatter-style format strings.
 CharSequence text = context.getString(R.string.appwidget_text_format,
 ExampleAppWidgetConfigure.loadTitlePref(context, appWidgetId),
"0x" + Long.toHexString(SystemClock.elapsedRealtime()));
// Construct the RemoteViews object. It takes the package name (in our case, it's our
// package, but it needs this because on the other side it's the widget host inflating
// the layout from our package).
 RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider);
 views.setTextViewText(R.id.appwidget_text, text);
// Tell the widget manager
 appWidgetManager.updateAppWidget(appWidgetId, views);
 }
 }  
    
    
    
  
public  class  ExampleAppWidgetProvider  extends  AppWidgetProvider  { 
public  void onUpdate ( Context context ,  AppWidgetManager appWidgetManager ,  int [] appWidgetIds )  { 
final  int N  = appWidgetIds . length ; 
// Perform this loop procedure for each App Widget that belongs to this provider 
for  ( int i = 0 ; i < N ; i ++)  { 
int appWidgetId  = appWidgetIds [ i ]; 
// Create an Intent to launch ExampleActivity 
Intent intent  =  new  Intent ( context ,  ExampleActivity . class ); 
PendingIntent pendingIntent  =  PendingIntent . getActivity ( context ,  0 , intent ,  0 ); 
// Get the layout for the App Widget and attach an on-click listener to the button 
RemoteViews views  =  new  RemoteViews ( context . getPackageName (), R . layout . appwidget_provider_layout ); 
views . setOnClickPendingIntent ( R . id . button , pendingIntent ); 
// Tell the AppWidgetManager to perform an update on the current App Widget 
appWidgetManager . updateAppWidget ( appWidgetId , views ); 
    } 
  } 
}


3 View layout

   只要你熟悉用 xml 怎么去定义 layout 的话,为 App Widget 定义一个 layout 还是很简单的。但是由于App Widget 的布局是基于 RemoteViews ,所以只能使用 RemoteViews 所支持的 layout 或者 view

RemoteViews 支持的 layout 和 view

Layout – FrameLayout 、LinearLayout、 RelativeLayou

View -- Analog、Clock、 Button、 Chronometer 、ImageButton、 ImageView、 ProgressBar 、TextView

注意:继承这些类的子类同样 不支持。

ApiDemo例子,appwidget_provider.xml文件。


<?xml version="1.0" encoding="utf-8"
 
  
<!-- Copyright (C) 2006 The Android
 
  
Licensed under the Apache
 
  
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.


-->
 
  
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
 
  
android:id="@+id/appwidget_text"
 
  
android:layout_width="wrap_content"
 
  
android:layout_height="wrap_content"
 
  
android:textColor="#ff000000"
 
  
/>


4 App Widget Configuration Activity

   这个 Activity 将通过 App Widget 自动启动,用户可以给 App Widget 设置有用的参数,比如 App Widget

   在 AndroidManifes.xml 中定义这个 Activity 和一般定义 Activity 基本没有区别, App Widget host 启动这个 Activity 需要一个 Action



<activity  android:name = ".ExampleAppWidgetConfigure" > 
 <intent-filter> 
 <action  android:name = "android.appwidget.action.APPWIDGET_CONFIGURE"     /> 
</intent-filter> 
</ activity >



   同样这个 Activity 必须在 AppWidgetProviderInfo  文件中定义 android:configure

   值得注意的是 App Widget host 调用 configuration Activity , configuration Activity 必须要返回一个结果 ( 必须包含 App Widget ID ) saved in the Intent extras as  EXTRA_APPWIDGET_ID。

ApiDemo例子,ExampleAppWidgetConfigure.java文件:

package com.example.android.apis.appwidget;
   

import android.app.Activity;
   
import android.appwidget.AppWidgetManager;
   
import android.content.Context;
   
import android.content.Intent;
   
import android.content.SharedPreferences;
   
import android.os.Bundle;
   
import android.util.Log;
   
import android.view.View;
   
import android.widget.EditText;
   

import java.util.ArrayList;
   

// Need the following import to get access to the app resources, since this
   
// class is in a sub-package.
   
import com.example.android.apis.R;
   


public 
   class ExampleAppWidgetConfigur
   e 
   extends Activity {
   
  
    
    
    
   static 
   final String TAG 
   = 
   "ExampleAppWidgetConfigure" ;
   

  
    
    
    
   private 
   static 
   final String PREFS_NAME
   
  
    
    
    
    
    
    
    
    
    
    
    
   = 
   "com.example.android.apis.appwidget.ExampleAppWidgetProvider" ;
   
  
    
    
    
   private 
   static 
   final String PREF_PREFIX_KEY 
   = 
   "prefix_" ;
   

  
    
    
    
   int mAppWidgetId 
   = AppWidgetManager.INVALID_APPWIDGET_ID;
   
  
    
    
    
   EditText mAppWidgetPrefix;
   

  
    
    
    
   public ExampleAppWidgetConfigur
   e() {
   
  
    
    
    
    
    
    
    
   super ();
   
  
    
    
    
   }
   

  
    
    
    
   @Override
   
  
    
    
    
   public 
   void onCreate(Bundle icicle) {
   
  
    
    
    
    
    
    
    
   super .onCreate(icicle);
   

  
    
    
    
    
    
    
    
   // Set the result to CANCELED. This will cause the widget host to cancel
   
  
    
    
    
    
    
    
    
   // out of the widget placement if they press the back button.
   
  
    
    
    
    
    
    
    
   setResult(RESULT_CANCELED);
   

  
    
    
    
    
    
    
    
   // Set the view layout resource to use.
   
  
    
    
    
    
    
    
    
   setContentView(R.layout.appwidget_configure);
   

  
    
    
    
    
    
    
    
   // Find the EditText
   
  
    
    
    
    
    
    
    
   mAppWidgetPrefix 
   = (EditText)findViewById(R.id.appwidget_prefix);
   

  
    
    
    
    
    
    
    
   // Bind the action for the save button.
   
  
    
    
    
    
    
    
    
   findViewById(R.id.save_button).setOnClickListener(mOnClickListener);
   

  
    
    
    
    
    
    
    
   // Find the widget id from the intent.  
   
  
    
    
    
    
    
    
    
   Intent intent 
   = getIntent();
   
  
    
    
    
    
    
    
    
   Bundle extras 
   = intent.getExtras();
   
  
    
    
    
    
    
    
    
   if (extras 
   != null) {
   
  
    
    
    
    
    
    
    
    
    
    
    
   mAppWidgetId 
   = extras.getInt(
   
  
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
   AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
   
  
    
    
    
    
    
    
    
   }
   

  
    
    
    
    
    
    
    
   // If they gave us an intent without the widget id, just bail.
   
  
    
    
    
    
    
    
    
   if (mAppWidgetId 
   == AppWidgetManager.INVALID_APPWIDGET_ID) {
   
  
    
    
    
    
    
    
    
    
    
    
    
   finish();
   
  
    
    
    
    
    
    
    
   }
   

  
    
    
    
    
    
    
    
   mAppWidgetPrefix.setText(loadTitlePref(ExampleAppWidgetConfigur
   e.
   this , mAppWidgetId));
   
  
    
    
    
   }
   

  
    
    
    
   View.OnClickListener mOnClickListener 
   = 
   new View.OnClickListener() {
   
  
    
    
    
    
    
    
    
   public 
   void onClick(View v) {
   
  
    
    
    
    
    
    
    
    
    
    
    
   final Context context 
   = ExampleAppWidgetConfigur
   e.
   this ;
   

  
    
    
    
    
    
    
    
    
    
    
    
   // When the button is clicked, save the string in our prefs and return that they
   
  
    
    
    
    
    
    
    
    
    
    
    
   // clicked OK.
   
  
    
    
    
    
    
    
    
    
    
    
    
   String titlePrefix 
   = mAppWidgetPrefix.getText().toString();
   
  
    
    
    
    
    
    
    
    
    
    
    
   saveTitlePref(context, mAppWidgetId, titlePrefix);
   

  
    
    
    
    
    
    
    
    
    
    
    
   // Push widget update to surface with newly set prefix
   
  
    
    
    
    
    
    
    
    
    
    
    
   AppWidgetManager appWidgetManager 
   = AppWidgetManager.getInstance(context);
   
  
    
    
    
    
    
    
    
    
    
    
    
   ExampleAppWidgetProvider
   .updateAppWidget(context, appWidgetManager,
   
  
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
   mAppWidgetId, titlePrefix);
   

  
    
    
    
    
    
    
    
    
    
    
    
   // Make sure we pass back the original appWidgetId
   
  
    
    
    
    
    
    
    
    
    
    
    
   Intent resultValue 
   = 
   new Intent();
   
  
    
    
    
    
    
    
    
    
    
    
    
   resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
   
  
    
    
    
    
    
    
    
    
    
    
    
   setResult(RESULT_OK, resultValue);
   
  
    
    
    
    
    
    
    
    
    
    
    
   finish();
   
  
    
    
    
    
    
    
    
   }
   
  
    
    
    
   };
   

  
    
    
    
   // Write the prefix to the SharedPreferences object for this widget
   
  
    
    
    
   static 
   void saveTitlePref(Context context, 
   int appWidgetId, String text) {
   
  
    
    
    
    
    
    
    
   SharedPreferences.Editor prefs 
   = context.getSharedPreferences(PREFS_NAME, 
   0 ).edit();
   
  
    
    
    
    
    
    
    
   prefs.putString(PREF_PREFIX_KEY 
   + appWidgetId, text);
   
  
    
    
    
    
    
    
    
   prefs.commit();
   
  
    
    
    
   }
   

  
    
    
    
   // Read the prefix from the SharedPreferences object for this widget.
   
  
    
    
    
   // If there is no preference saved, get the default from a resource
   
  
    
    
    
   static String loadTitlePref(Context context, 
   int appWidgetId) {
   
  
    
    
    
    
    
    
    
   SharedPreferences prefs 
   = context.getSharedPreferences(PREFS_NAME, 
   0 );
   
  
    
    
    
    
    
    
    
   String prefix 
   = prefs.getString(PREF_PREFIX_KEY 
   + appWidgetId, null);
   
  
    
    
    
    
    
    
    
   if (prefix 
   != null) {
   
  
    
    
    
    
    
    
    
    
    
    
    
   return prefix;
   
  
    
    
    
    
    
    
    
   } 
   else {
   
  
    
    
    
    
    
    
    
    
    
    
    
   return context.getString(R.string.appwidget_prefix_default);
   
  
    
    
    
    
    
    
    
   }
   
  
    
    
    
   }
   

  
    
    
    
   static 
   void deleteTitlePref(Context context, 
   int appWidgetId) {
   
  
    
    
    
   }
   

  
    
    
    
   static 
   void loadAllTitlePrefs(Context context, ArrayList
   < Integer
   > appWidgetIds,
   
  
    
    
    
    
    
    
    
    
    
    
    
   ArrayList
   < String
   > texts) {
   
  
    
    
    
   }
   
 }

标签:widget,Context,App,Widget,context,Android,Frame,android
From: https://blog.51cto.com/u_548275/6885687

相关文章

  • android网络通信之HTTP协议教程实…
    在现在的开发和应用中,网络通讯是必不可少的。虽然还是比较怀念小时候,抱着一台95在那里玩单机游戏玩的天昏地暗的时光,但是,现在,就算一个幼儿园的小盆友如果问你要手机玩游戏,突然发现居然买不了冰激凌草莓果汁什么的去喂talkinggina,或者切出一个超爆的水果分数却传不到网上去炫......
  • Android AIDL——实现机制浅析
    1.基于前面写的aidl使用,这段时间准备研究ActivityManager框架,对aidl进行了更深入的研究,因为android框架大量使用了进程通信机制,所以,在研究androidframework前认真研究一下AIDL的实现机制十分有必要的3.aidl接口packagecom.cao.android.demos.binder.aidl;importcom.cao.an......
  • Android NFC简介
    目录:AndroidNFC1 简介1.1 什么是 NFC1.2Android 上的 NFC1.3Android 中的 NFC 通讯机制2 用法2.1 读取 tag2.2 发送消息2.2.1 发送过程2.2.2NDEF 消息格式1 简介1.1 什么是 NFC近场通讯 (NearFiledCommunication) 技术是一种近距离的高频无线......
  • Robot Framework 自动化测试部署常见问题及处理方法(一)
    1.在Python>>Scripts中运行pythonride.py时报错现象:1Traceback(mostrecentcalllast):2File“E:\Python27\lib\site-packages\robotide\application\application.py”,line56,inOnInit3self.frame=RideFrame(self,self._controller)4File“E:\P......
  • Robot Framework自动化测试随笔(二)
    二、Web自动化(1)1.安装selenium2library库pipinstallrobotframework-selenium2library 2.指定报告的生成路径在【Run】标签下,配置Arguments路径:-dD:\python37\log 3.网页元素自动化,对所有元素操作分两步:⑴定位元素(谷歌、火狐建议使用xpath,IE建议使用css)⑵对元素......
  • Android-组件属性
    ImageView:app:tint=“”(tint:染色)作用:将非透明像素点染成指定颜色 EditText:android:selectAllOnFocus="true"作用:输入框获取焦点后,获取到所有文本内容 ......
  • AndroidAnnotations 自定义控件 ant编译 找不到类
    问题:今天使用jenkins+ant编译android项目,一直编译不通过,报错内容就是,自定义控件找不到类。确认了几次svn提交,项目代码完全提交,所以想到是不是代码的问题。故回头查询代码。在代码中使用了下划线类。这个类是在AA中自动生成的,而报错的地方,正是编译生成的地方,觉得可能和编......
  • Android从相册、照相机选择图片(支持4.4+,KIKAT以上)
    开发都会遇到从手机的相册和照相机选择图片的功能,下面是一段通用的代码,用来选择手机中的图片,以后用的时候,直接调用就可以了。使用到的类属性publicfinalstaticintCONSULT_DOC_PICTURE=1000;publicfinalstaticintCONSULT_DOC_CAMERA=1001;privateintSELECT_PICTURE......
  • AndroidAnnotations 使用在library项目中出现无法找到R文件下资源索引的错误
    AndroidAnnotations使用在library项目中出现无法找到R文件下资源索引的错误使用AndroidAnnotations(以下简称AA)已经有一段时间了,挺好用的,基本上完全可以满足Android开发需要,可以简化代码,所以现在在岗编写的所有的项目都是基于AA实现的。AA现在最新版本为3.2官方地址:http://android......
  • Kotlin 踩坑日记(六)Android studio 3.0.0 Canary 4 Instant Run
    前言宁夏的特色假日,开斋节放了5天,今天回来上班。放假前,Androidstudio3.0发布了Canary4的升级,因为即将放假,所以就没有升级,节后上班第一天,就安排升级并且试用一下。DebugApk找不到Application类没有别的问题,只是在InstantRun环境下,找不到App的Application类,应用安装成功后,......