Instant Buy Android API Tutorial

转自:https://developers.google.com/wallet/instant-buy/android/tutorial

This tutorial guides you through integrating Instant Buy into a purchase flow, in the context of an example bike store. The tutorial provides details and complete source code to help you complete the the integration steps summarized in the integration overview, with the end goal of reproducing a flow similar to  the Instant Buy API Process Flow. If you‘d like to review the sample app first, you can download the APK file.

A significant portion of the Instant Buy API‘s functionality is provided as part of Google Play Services, the core services for developing on Android. For the purposes of this tutorial, we‘ll assume that you are familiar with the basic concepts and skills of application development for the Android platform. If you need to learn about Android development before getting started, work through some lessons in the Training for Android Developers.

Note: With the integration described here, merchants can process payments using their existing payment infrastructure. If you are looking for a solution where Google processes payments for you, use the Android In-App Billing SDK.

Contents

  1. Set up the tutorial

    1. Obtain credentials and a client ID for your app
    2. Set up the sample and Google Play Services
  2. About WalletFragment
  3. Create a masked wallet request
  4. Add a  Buy with Google  button and request the masked wallet
  5. Confirm the purchase and set the masked wallet
  6. Request the full wallet
  7. Initialize the Google API client
  8. Retrieve the full wallet
  9. Notify Google Wallet of your Transaction Processing
  10. Handle errors
  11. Enable Wallet optimization in your manifest

Set up the tutorial

To get started with this tutorial, create a client ID for your project, download and review the source code, and set up Google Play services.

Obtain credentials and a client ID for your app

To access the Instant Buy Android API, you‘ll need to obtain a client ID for OAuth 2.0 authorization in the Google Developers Console.  The client ID is generated automatically when you register your app.. You‘ll also need the SHA1 fingerprint in your developer‘s key to generate a client ID.

  1. Go to the Google Developers Console.
  2. Select a project, or create a new one.
  3. In the sidebar on the left, select APIs & auth.
  4. In the sidebar on the left, select Credentials.
  5. To register your certificate, you need to get the certificate‘s SHA1 fingerprint, by switching to a terminal window and running the the Keytool utility:    
    keytool -exportcert -alias androiddebugkey -keystore path_to_debug_or_production_keystore -list -v

    Note: For Eclipse, the debug keystore is typically located at ~/.android/debug.keystore.

    For the debug keystore, the password is android.

    The Keytool prints the fingerprint to the shell. For example:

$ keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v
Enter keystore password: Type "android" if using debug.keystore
Alias name: androiddebugkey
Creation date: Aug 27, 2012
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Android Debug, O=Android, C=US
Issuer: CN=Android Debug, O=Android, C=US
Serial number: 503bd581
Valid from: Mon Aug 27 13:16:01 PDT 2012 until: Wed Aug 20 13:16:01 PDT 2042
Certificate fingerprints:
   MD5:  1B:2B:2D:37:E1:CE:06:8B:A0:F0:73:05:3C:A3:63:DD
   SHA1: D8:AA:43:97:59:EE:C5:95:26:6A:07:EE:1C:37:8E:F4:F0:C8:05:C8
   SHA256: F3:6F:98:51:9A:DF:C3:15:4E:48:4B:0F:91:E3:3C:6A:A0:97:DC:0A:3F:B2:D2:E1:FE:23:57:F5:EB:AC:13:30
   Signature algorithm name: SHA1withRSA
   Version: 3

Copy the SHA1 fingerprint, which is highlighted in the example above.

Important: When you prepare to release your app to your users, you will follow these steps again and create a new OAuth 2.0 client ID for your production app. For production apps, you will use your own private key to sign the production app‘s .apk file. For more information, see Signing your applications.

  • Back in the Console, do the following:

    1. Click Create New Client ID.
    2. Select Installed application and Android.
    3. In the Package name field, enter your Android‘s app‘s package name.
    4. Paste the SHA1 fingerprint into the Signing certificate fingerprint text box.
    5. Click Create Client ID.

Note: You‘ll need to create two separate sets of OAuth 2.0 credentials: one set for developing and testing in the sandbox, and another set when you go to production.

Set up the sample and Google Play Services

Follow these setup instructions to import both the Google Play Services library as well as the Google Wallet Instant Buy sample. You can find the sample at android-sdk/extras/google/google_play_services/samples/wallet. If you don‘t already have it, you‘ll need to get the Android SDK.

About WalletFragment

This tutorial demonstrates typical usage of the WalletFragment class. The Instant Buy Android API provides this class to handle user events and to automate key parts of the purchase lifecycle. As illustrated in this tutorial and sample, an app would typically use instances of the wallet fragment class in two key areas of the purchase flow:

  • A purchase fragment (defined by WalletFragmentMode.BUY_BUTTON), which displays a Buy with Google button and sets a masked wallet request to send to Google Wallet.
  • A confirmation fragment (defined by WalletFragmentMode.SELECTION_DETAILS) , which displays "change" buttons to let users optionally modify the masked wallet, and sets the masked wallet.

Note: Though this tutorial invokes the the wallet fragment programatically, you also can add it to an activity layout via XML. For more information, see WalletFragment.

The final calls for loading the full wallet are not included in the automated functionality of the WalletFragment class. Instead, these calls are encapsulated in the FullWalletConfirmationButtonFragment class of the sample app. Relevant calls are described in detail in Retrieve the Full Wallet.

Create a masked wallet request

You‘ll need to create an instance of MaskedWalletRequest to invoke the Instant Buy Android API to retrieve the masked wallet information (such as shipping address, masked backing instrument number, and cart items). The MaskedWalletRequest object must be passed in when you initialize the purchase wallet fragement in the next section.

At this point, you won‘t have the user‘s chosen shipping address, so you‘ll need to create an estimate of the shipping costs and tax. If you set the shopping cart as shown below (highly recommended), make sure  the cart total matches the sum of the line items added to the cart.

Currently, InstantBuy does not support non-US transactions.  The only valid value for currencyCode is  CURRENCY_CODE_USD.

Here is an example of creating the masked wallet request using the builder pattern:

MaskedWalletRequest maskedWalletRequest =
  MaskedWalletRequest.newBuilder()
  .setMerchantName(Constants.MERCHANT_NAME)
  .setPhoneNumberRequired(true)
  .setShippingAddressRequired(true)
  .setCurrencyCode("USD")
  .setShouldRetrieveWalletObjects(true)
  .setCart(Cart.newBuilder()
      .setCurrencyCode(Constants.CURRENCY_CODE_USD)
      .setTotalPrice("150.00")
      .addLineItem(LineItem.newBuilder()
              .setCurrencyCode(Constants.CURRENCY_CODE_USD)
              .setDescription(itemInfo.name)
              .setQuantity("1")
              .setUnitPrice(toDollars(context, itemInfo.priceMicros))
              .setTotalPrice("130.00")
              .build())
      .addLineItem(LineItem.newBuilder()
              .setCurrencyCode(Constants.CURRENCY_CODE_USD)
              .setDescription(Constants.DESCRIPTION_LINE_ITEM_SHIPPING)
              .setRole(LineItem.Role.SHIPPING)
              .setTotalPrice("13.00")
              .build())
      .addLineItem(LineItem.newBuilder()
              .setCurrencyCode(Constants.CURRENCY_CODE_USD)
              .setDescription(Constants.DESCRIPTION_LINE_ITEM_TAX)
              .setRole(LineItem.Role.TAX)
              .setTotalPrice("7.00")
              .build())
      .build())
  .setEstimatedTotalPrice("150.00")
  .build();

This masked wallet object is the first parameter taken by the loadMaskedWallet call described in the next section.

Note: In this step, you‘re requesting just the masked information and not the actual credit card information. The total amount in this request is the order amount exclusive of tax and shipping.

Add a Buy with Google button and request the masked wallet

Next, construct an instance of WalletFragment to add to your checkout activity. This fragment, when configured in BUY_BUTTON mode with the appropriate button text as shown below, displays the Buy with Google button and handles click events for your app:

private void createAndAddWalletFragment() {
    WalletFragmentStyle walletFragmentStyle = new WalletFragmentStyle()
            .setBuyButtonText(BuyButtonText.BUY_WITH_GOOGLE)
            .setBuyButtonWidth(Dimension.MATCH_PARENT);

    WalletFragmentOptions walletFragmentOptions = WalletFragmentOptions.newBuilder()
            .setEnvironment(WalletConstants.ENVIRONMENT_SANDBOX)
            .setFragmentStyle(walletFragmentStyle)
            .setTheme(WalletConstants.THEME_HOLO_LIGHT)
            .setMode(WalletFragmentMode.BUY_BUTTON)
            .build();
    mWalletFragment = SupportWalletFragment.newInstance(walletFragmentOptions);

When you initialize the purchase fragment, pass in the maskedWalletRequest that you created in the previous step, as well as the code REQUEST_CODE_MASKED_WALLET used to uniquely identify this call in the onActivityResult() callback:

String accountName = ((BikestoreApplication) getApplication()).getAccountName();
  MaskedWalletRequest maskedWalletRequest =
          WalletUtil.createMaskedWalletRequest(Constants.ITEMS_FOR_SALE[mItemId]);
  WalletFragmentInitParams.Builder startParamsBuilder = WalletFragmentInitParams.newBuilder()
          .setMaskedWalletRequest(maskedWalletRequest)
          .setMaskedWalletRequestCode(REQUEST_CODE_MASKED_WALLET)
          .setAccountName(accountName);
  mWalletFragment.initialize(startParamsBuilder.build());

  // add Wallet fragment to the UI
  getSupportFragmentManager().beginTransaction()
          .replace(R.id.dynamic_wallet_button_fragment, mWalletFragment)
          .commit();

When the user clicks the buy button, the masked wallet is retrieved and returned in the onActivityResult of the enclosing activity as shown below. If the user has not preauthorized this app to retrieve Wallet information, Google Wallet presents a chooser dialog, handles preauthorization, and returns control to the app.

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    // retrieve the error code, if available
    int errorCode = -1;
    if (data != null) {
        errorCode = data.getIntExtra(WalletConstants.EXTRA_ERROR_CODE, -1);
    }
    switch (requestCode) {
        case REQUEST_CODE_MASKED_WALLET:
            switch (resultCode) {
                case Activity.RESULT_OK:
                    MaskedWallet maskedWallet =
                            data.getParcelableExtra(WalletConstants.EXTRA_MASKED_WALLET);
                    launchConfirmationPage(maskedWallet);
                    break;
                case Activity.RESULT_CANCELED:
                    break;
                default:
                    handleError(errorCode);
                    break;
            }
            break;

Confirm the purchase and set the masked wallet

After the app obtains the masked wallet, it should present a confirmation page showing the total cost of the items purchased in the transaction. To do this, construct an instance of WalletFragment in Mode.SELECTION_DETAILS as shown:

WalletFragmentStyle walletFragmentStyle = new WalletFragmentStyle()
        .setMaskedWalletDetailsTextAppearance(
                R.style.BikestoreWalletFragmentDetailsTextAppearance)
        .setMaskedWalletDetailsHeaderTextAppearance(
                R.style.BikestoreWalletFragmentDetailsHeaderTextAppearance)
        .setMaskedWalletDetailsBackgroundColor(
                getResources().getColor(R.color.bikestore_white))
        .setMaskedWalletDetailsButtonBackgroundResource(
                R.drawable.bikestore_btn_default_holo_light)
        .setMaskedWalletDetailsLogoTextColor(
                getResources().getColor(R.color.wallet_dark_grey));

WalletFragmentOptions walletFragmentOptions = WalletFragmentOptions.newBuilder()
        .setEnvironment(WalletConstants.ENVIRONMENT_SANDBOX)
        .setFragmentStyle(walletFragmentStyle)
        .setTheme(WalletConstants.THEME_HOLO_LIGHT)
        .setMode(WalletFragmentMode.SELECTION_DETAILS)
        .build();
mWalletFragment = SupportWalletFragment.newInstance(walletFragmentOptions);

Note that this method also sets a number of WalletFragmentStyleoptions controlling the appearance of the following screen:

At this point the app has the shipping address and billing address, so it can calculate exact total purchase price and display it. This activity also allows the user to change the Google Wallet payment instrument and change the shipping address for the purchase.

The “Change” buttons are particularly important for  preauthorized users, who proceed directly to this confirmation page when they   click the Buy with Google button. If the user clicks a    “Change” button, the fragment returns a new masked wallet in    onActivityResult of the enclosing activity.

Request the full wallet

When the user confirms the order, you are ready to request the full wallet. The full wallet Request should have the total charge that you are requesting including exact shipping, handling and tax. You must include the GoogleTransactionId that you received in the masked wallet response.

Create a FullWalletRequest object that contains the various line items (including tax and shipping if necessary) and a Cart object.

FullWalletRequest fullWalletRequest = FullWalletRequest.newBuilder()
  .setGoogleTransactionId(googleTransactionId)
  .setCart(Cart.newBuilder()
          .setCurrencyCode(Constants.CURRENCY_CODE_USD)
          .setTotalPrice(toDollars(context, itemInfo.getTotalPrice()))
          .addLineItem(LineItem.newBuilder()
                  .setCurrencyCode(Constants.CURRENCY_CODE_USD)
                  .setDescription(itemInfo.name)
                  .setQuantity("1")
                  .setUnitPrice(toDollars(context, itemInfo.priceMicros))
                  .setTotalPrice(toDollars(context, itemInfo.priceMicros))
                  .build())
          .addLineItem(LineItem.newBuilder()
                  .setCurrencyCode(Constants.CURRENCY_CODE_USD)
                  .setDescription(Constants.DESCRIPTION_LINE_ITEM_SHIPPING)
                  .setRole(LineItem.Role.SHIPPING)
                  .setTotalPrice(toDollars(context, itemInfo.shippingPriceMicros))
                  .build())
          .addLineItem(LineItem.newBuilder()
                  .setCurrencyCode(Constants.CURRENCY_CODE_USD)
                  .setDescription(Constants.DESCRIPTION_LINE_ITEM_TAX)
                  .setRole(LineItem.Role.TAX)
                  .setTotalPrice(toDollars(context, itemInfo.taxMicros))
                  .build())
          .build())
  .build();

Currently, InstantBuy does not support non-US transactions.  The only valid value for currencyCode is  CURRENCY_CODE_USD.

Initialize the Google API client

The GoogleApiClient object wraps a ServiceConnection to Google Play services and is used to communicate with the Instant Buy API. Though it is not required when working with WalletFragment, you‘ll need to initialize it to retrieve the full wallet.

The GoogleApiClient becomes functional after the asynchronous connection has been established with the service, indicating that:

  • Google Play services is running on the device and your Activity  successfully bound the service connection,
  • the user has selected an account that they wish to use with your app, and
  • the user‘s account has granted the permissions that your app is requesting.

The following code snippet (from a fragment) illustrates how to instantiate a Google API client for your Instant Buy app and then connect:

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

    ...

mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
        .addConnectionCallbacks(this)
        .addOnConnectionFailedListener(this)
        .setAccountName(accountName)
        .addApi(Wallet.API, new Wallet.WalletOptions.Builder()
            .setEnvironment(Constants.WALLET_ENVIRONMENT)
            .setTheme(WalletConstants.THEME_HOLO_LIGHT)
            .build())
        .build();

      ...

@Override
public void onStart() {
    super.onStart();

    // Connect to Google Play Services
    mGoogleApiClient.connect();
}
  • Environment is a parameter in WalletOptions whose value indicates the environment (production or sandbox) in which the server supporting the app is running. Its value may be WalletConstants.ENVIRONMENT_PRODUCTION or WalletConstants.ENVIRONMENT_SANDBOX  For testing and development always use only the sandbox environment.
  • Theme is another WalletOptions parameter to set the UI theme for the app. A value of WalletConstants.THEME_HOLO_LIGHT optionally sets a light UI theme instead of the default dark theme (WalletConstants.THEME_HOLO_DARK).
  • accountName is an optional string containing the Google account name (email address).
  • connectionCallBacks is an object that implements the interface com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks. Android calls the onActivityResult method of the object to notify the app when it connects and disconnects with Google Play Services.
  • OnconnectionFailedListener is an object that implements the interface com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener.  Android calls the onActivityResult method of the object to notify the app of a failed attempt to connect with Google Play Services.

This call results in a callback to one of two methods: OnConnectionCallbackListener.onConnected if the connection succeeded, or OnConnectionFailedListener.onConnectionFailed if the connection failed. The callback receives an error code which describes the reason for the failure.

Retrieve the full wallet

Once you have constructed the full wallet request instance, call the loadFullWallet method.  When the full wallet request is completed, Google calls the onActivityResult method, passing the intent result.

private void getFullWallet() {
    Wallet.Payments.loadFullWallet(mGoogleApiClient,
            WalletUtil.createFullWalletRequest(mItemInfo,
                    mMaskedWallet.getGoogleTransactionId()),
            REQUEST_CODE_RESOLVE_LOAD_FULL_WALLET);

...

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    mProgressDialog.hide();

    int errorCode = -1;
    if (data != null) {
        errorCode = data.getIntExtra(WalletConstants.EXTRA_ERROR_CODE, -1);
    }

    switch (requestCode) {
        case REQUEST_CODE_RESOLVE_ERR:
            if (resultCode == Activity.RESULT_OK) {
                mGoogleApiClient.connect();
            } else {
                handleUnrecoverableGoogleWalletError(errorCode);
            }
            break;
        case REQUEST_CODE_RESOLVE_LOAD_FULL_WALLET:
            switch (resultCode) {
                case Activity.RESULT_OK:
                    if (data.hasExtra(WalletConstants.EXTRA_FULL_WALLET)) {
                        FullWallet fullWallet =
                                data.getParcelableExtra(WalletConstants.EXTRA_FULL_WALLET);
                        fetchTransactionStatus(fullWallet);

Once you have retrieved the full wallet in the onActivityResult() callback, you have enough information to proceed to payment processing for this transaction. The ProxyCard is a valid payment card, except it is distinct from the user’s actual payment instrument in Google Wallet. You can access the details in the ProxyCard from the full wallet as shown below:

String accountNumber  =  fullWallet.getProxyCard().getPan();
String securityCvv  = fullWallet.getProxyCard().getCvn();
int expirationYear = fullWallet.getExpirationYear();
int expirationMonth = fullWallet.getExpirationMonth();
Address billingAddress = fullWallet.getBillingAddress();
Address shippingAddress = fullWallet.getShippingAddress();

With this, you can charge this card in the amount that you requested in the full wallet request, just as you would charge any other credit card received in your app in non Google Wallet flow.

Notify Google Wallet of your Transaction Processing

Once you have obtained the payment instrument information from the ProxyCard and processed the payment, notify Google Wallet of the success or failure of the payment. Based on the response from your server, create the NotifyTransactionStatusRequest object.

Wallet.Payments.notifyTransactionStatus(mGoogleApiClient,
        WalletUtil.createNotifyTransactionStatusRequest(fullWallet.getGoogleTransactionId(),
                NotifyTransactionStatusRequest.Status.SUCCESS));

Note: Make sure to send the transaction status in real time, only when the payment is actually processed. In special use cases with deferred processing, don‘t send the status until you have completed payment processing.

Finally, you may want to clean up by calling the Google API Client’s disconnect method. This is typically done in the onStop() method of your Activity.

@Override
public void onStop() {
  super.onStop();
  mGoogleApiClient.disconnect();
}

Handle errors

Since a typical activity or fragment can call multiple Google API methods, it‘s advisable to have a common code block in onActivityResult()that fetches error codes.

    int errorCode = -1;
    if (data != null) {
        errorCode = data.getIntExtra(
            WalletConstants.EXTRA_ERROR_CODE, -1);
    }

After you fetch the codes, you can handle errors in the default block of a switch/case statement by calling handleError(errorCode):

void handleError(int errorCode) {
    switch (errorCode) {
        case WalletConstants.ERROR_CODE_SPENDING_LIMIT_EXCEEDED:
            Toast.makeText(getActivity(),
                    getString(R.string.spending_limit_exceeded, errorCode),
                    Toast.LENGTH_LONG).show();
            break;
        case WalletConstants.ERROR_CODE_INVALID_PARAMETERS:
        case WalletConstants.ERROR_CODE_AUTHENTICATION_FAILURE:
        case WalletConstants.ERROR_CODE_BUYER_ACCOUNT_ERROR:
        case WalletConstants.ERROR_CODE_MERCHANT_ACCOUNT_ERROR:
        case WalletConstants.ERROR_CODE_SERVICE_UNAVAILABLE:
        case WalletConstants.ERROR_CODE_UNSUPPORTED_API_VERSION:
        case WalletConstants.ERROR_CODE_UNKNOWN:
        default:
            // unrecoverable error
            mGoogleWalletDisabled = true;
            displayGoogleWalletErrorToast(errorCode);
            break;
    }
}

You can augment this implementation to handle your app‘s specific needs. For example, if you support multiple payment methods, you can choose to use another payment method for unrecoverable errors.

Enable Wallet optimization in your manifest

You can greatly improve your users‘ first-time experience by enabling Wallet optimization in your app manifest. This option signals to Google Play Services that your app uses Google Wallet, which can then perform optimizations when the user first launches your app.

To enable Wallet optimization, add the following broadcast receiver to your app manifest:

    <receiver
        android:name="com.google.android.gms.wallet.EnableWalletOptimizationReceiver"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.android.gms.wallet.ENABLE_WALLET_OPTIMIZATION" />
        </intent-filter>
    </receiver>

Enabling Wallet optimization is optional, but highly recommended for its enhancement of performance and user experience for your app.

时间: 2024-10-03 23:00:20

Instant Buy Android API Tutorial的相关文章

翻译Android API Guides: App Manifest

原文在这里:http://developer.android.com/guide/topics/manifest/manifest-intro.html *Manifest译作"清单",这里沿用英文便于理解,其它术语同理. **文中链接都会跳转到android开发者网站. App Manifest 每一个应用都必须在它的根目录有一份AndroidManifest.xml文件(必须使用这个名字).Android系统必须在运行应用的任何代码之前了解一些重要信息,这些信息就来自于这份mani

Google Android API官网封杀了,没法查android技术资料的3种解决方案

1.从uhdesk上访问简化版android api在线文档(反应速度极快) http://www.uhdesk.com/simpleandroidoc/index.html 2.下载chm本地文档(19M的样子) http://www.uhdesk.com/doc/Andorid%20API%20docs.chm 3.使用完整版本android api在线文档(明显这个域名的服务器跟不上) http://www.uhdesk.com/androidoc/index.html Google An

android api实现高斯模糊,且兼容低版本

一.利用android api实现高斯模糊 关于高斯模糊网上已经有很多不错的文章介绍了,在这里就不重复了.先来看一个效果 效果已经看到了,就来看看怎么实现的吧.首先是实现高斯模糊的核心代码 <span style="white-space:pre"> </span>public static Bitmap blurBitmap(Bitmap bitmap, Context context) { // 用需要创建高斯模糊bitmap创建一个空的bitmap Bit

Json解析速度比较-Android API、Gson、Fastjson

IOS现成的API里的json解析速度非常快,这里就不说了,今天对比一下Android里面json的解析库. 首先第一个是Android API里面自带的json解析,其次是谷歌提供的Gson解析库(开源),其次是在网上看到的解析很快速的阿里巴巴分享的Fastjson包.Android自带的json解析大家一定都很熟悉了,这里不介绍了,这里详细说说谷歌提供的另一套解析库Gson: gson的使用方法非常的简单.只需要将需要解析的json字符串和对应的Bean类xing型传递给GSON类的from

a new Webcam Api Tutorial in C++ for Windows(Windows Media Foundation)--WMF

Sample source code: http://pan.baidu.com/s/1o60VAEA Foword from: http://www.dreamincode.net/forums/topic/347938-a-new-webcam-api-tutorial-in-c-for-windows/page__st__0%26 Well, A long time ago I introduced a Webcam Tutorial. It was for Video For Windo

Android Studio无法关联Api23源码-提示Souces for android api 23 platform not found

最近升级了As,然后忽然就关联不上源码了,很不方便,找个Activity的源码都只有outline没有解释,还提示这个错误: Decompiled .class file, bytecode version: Souces for android api 23 platform not found 在D:\Android\sdk\sources\android-23明明下载了源码,找了半天,原来是AS的默认配置有问题.最后的解决方法在 StackOverFlow的这个帖子上: Sources f

Android API在不同版本系统上的兼容性

随着安卓版本的不断更新,新的API不断涌出,有时候高版本的API会在低版本crash的. 如果minSdkVersion设置过低,在build的时候,就会报错(Call requires API level 17 (current min is 9)): 这时候为了编译可以通过,可以添加 @SuppressLint("NewApi") 或者 @TargeApi(9)注解. 这样只是编译通过,运行时依然会crash的. 正确的做法 为了运行时不报错, 需要: 判断运行时版本,在低版本系统

Android 如何在Eclipse中查看Android API源码 及 support包源码

当我们阅读android API开发文档时候,上面的每个类,以及类的各个方法都是已经写好的方法和控件,可是我们只是在搬来使用,不知道它的原理,它是如何被实现的.android系统是开源的,所以谷歌官方在每发布一个版本的时候都会放出它对应的API源码的,让我们可以深入了解android的API实现过程,这就是开源的魅力.如果我们从API源码的角度去了解了开发过程,那样对于作为开发人员的我们,便会对他有更深入的体会,有助于日后的软件开发. 比如查看Activity的源码,如图 也可以查看系统方法怎么

Android API 中文(77)——AdapterView.OnItemSelectedListener

前言 本章内容是android.widget.AdapterView.OnItemSelectedListener,版本为Android 2.3 r1,翻译来自"cnmahj",欢迎大家访问他的博客:http://android.toolib.net/blog/,再次感谢"cnmahj"!欢迎你一起参与Android API 的中文翻译,联系我[email protected]. 声明 欢迎转载,但请保留文章原始出处:) 博客园:http://www.cnblogs