2013-11-20 23 views
21

के अंदर नई एंड्रॉइड विज्ञापनदाता आईडी का उपयोग करना यह बहुत समझ में आता है कि एंड्रॉइड विज्ञापन एसडीके एंड्रॉइड के नए विज्ञापनदाता आईडी का उपयोग करेंगे।एसडीके

ऐसा लगता है कि आप यहां Google सेवाओं एसडीके का उपयोग कर आईडी प्राप्त कर सकते हैं, जैसा कि यहां बताया गया है: http://developer.android.com/google/play-services/id.html

Google Play सेवाओं के SDK का उपयोग, गूगल प्ले-services_lib परियोजना है, जो कई समस्याओं का कारण बनता संदर्भित की आवश्यकता है:

  1. SDK का एक बहुत जार, जिसका अर्थ है कि वे गूगल प्ले-services_lib उपयोग नहीं कर सकते हैं जैसा है (क्योंकि वे संसाधन शामिल नहीं कर सकते हैं)।
  2. यदि मैं केवल विज्ञापनदाता आईडी चाहता हूं, तो मुझे अपनी परियोजना में google-play-services_lib जोड़ने की आवश्यकता है, जो लगभग 1 एमबी वजन करता है।

क्या संसाधनों का उपयोग किए बिना केवल विज्ञापनदाता आईडी प्राप्त करने का कोई तरीका है?

उत्तर

34

यदि आपको केवल विज्ञापनदाता की आवश्यकता है, तो मैं एक ही समस्या में भाग गया था, अगर आप सीधे Google Play सेवा से किसी इरादे का उपयोग कर बातचीत कर सकते हैं। कस्टम वर्ग का उदाहरण:

import java.io.IOException; 
import java.util.concurrent.LinkedBlockingQueue; 
import android.content.ComponentName; 
import android.content.Context; 
import android.content.Intent; 
import android.content.ServiceConnection; 
import android.content.pm.PackageManager; 
import android.os.IBinder; 
import android.os.IInterface; 
import android.os.Looper; 
import android.os.Parcel; 
import android.os.RemoteException; 

public final class AdvertisingIdClient { 

public static final class AdInfo { 
    private final String advertisingId; 
    private final boolean limitAdTrackingEnabled; 

    AdInfo(String advertisingId, boolean limitAdTrackingEnabled) { 
     this.advertisingId = advertisingId; 
     this.limitAdTrackingEnabled = limitAdTrackingEnabled; 
    } 

    public String getId() { 
     return this.advertisingId; 
    } 

    public boolean isLimitAdTrackingEnabled() { 
     return this.limitAdTrackingEnabled; 
    } 
} 

public static AdInfo getAdvertisingIdInfo(Context context) throws Exception { 
    if(Looper.myLooper() == Looper.getMainLooper()) throw new IllegalStateException("Cannot be called from the main thread"); 

    try { PackageManager pm = context.getPackageManager(); pm.getPackageInfo("com.android.vending", 0); } 
    catch (Exception e) { throw e; } 

    AdvertisingConnection connection = new AdvertisingConnection(); 
    Intent intent = new Intent("com.google.android.gms.ads.identifier.service.START"); 
    intent.setPackage("com.google.android.gms"); 
    if(context.bindService(intent, connection, Context.BIND_AUTO_CREATE)) { 
     try { 
      AdvertisingInterface adInterface = new AdvertisingInterface(connection.getBinder()); 
      AdInfo adInfo = new AdInfo(adInterface.getId(), adInterface.isLimitAdTrackingEnabled(true)); 
      return adInfo; 
     } catch (Exception exception) { 
      throw exception; 
     } finally { 
      context.unbindService(connection); 
     } 
    }  
    throw new IOException("Google Play connection failed");  
} 

private static final class AdvertisingConnection implements ServiceConnection { 
    boolean retrieved = false; 
    private final LinkedBlockingQueue<IBinder> queue = new LinkedBlockingQueue<IBinder>(1); 

    public void onServiceConnected(ComponentName name, IBinder service) { 
     try { this.queue.put(service); } 
     catch (InterruptedException localInterruptedException){} 
    } 

    public void onServiceDisconnected(ComponentName name){} 

    public IBinder getBinder() throws InterruptedException { 
     if (this.retrieved) throw new IllegalStateException(); 
     this.retrieved = true; 
     return (IBinder)this.queue.take(); 
    } 
} 

private static final class AdvertisingInterface implements IInterface { 
    private IBinder binder; 

    public AdvertisingInterface(IBinder pBinder) { 
     binder = pBinder; 
    } 

    public IBinder asBinder() { 
     return binder; 
    } 

    public String getId() throws RemoteException { 
     Parcel data = Parcel.obtain(); 
     Parcel reply = Parcel.obtain(); 
     String id; 
     try { 
      data.writeInterfaceToken("com.google.android.gms.ads.identifier.internal.IAdvertisingIdService"); 
      binder.transact(1, data, reply, 0); 
      reply.readException(); 
      id = reply.readString(); 
     } finally { 
      reply.recycle(); 
      data.recycle(); 
     } 
     return id; 
    } 

    public boolean isLimitAdTrackingEnabled(boolean paramBoolean) throws RemoteException { 
     Parcel data = Parcel.obtain(); 
     Parcel reply = Parcel.obtain(); 
     boolean limitAdTracking; 
     try { 
      data.writeInterfaceToken("com.google.android.gms.ads.identifier.internal.IAdvertisingIdService"); 
      data.writeInt(paramBoolean ? 1 : 0); 
      binder.transact(2, data, reply, 0); 
      reply.readException(); 
      limitAdTracking = 0 != reply.readInt(); 
     } finally { 
      reply.recycle(); 
      data.recycle(); 
     } 
     return limitAdTracking; 
    } 
} 
} 

सुनिश्चित करें कि आप इसे मुख्य UI थ्रेड से नहीं बुला रहे हैं। उदाहरण के लिए, की तरह कुछ का उपयोग करें:

new Thread(new Runnable() {   
    public void run() { 
     try { 
      AdInfo adInfo = AdvertisingIdClient.getAdvertisingIdInfo(context); 
      advertisingId = adInfo.getId(); 
      optOutEnabled = adInfo.isLimitAdTrackingEnabled(); 
     } catch (Exception e) { 
      e.printStackTrace();        
     }      
    } 
}).start(); 
+0

मुझे लगता है कि यह उपयोग करना खतरनाक है। क्या इस तरह कुछ दस्तावेज कहीं भी है? – Javanator

+0

खतरनाक क्यों? https://developer.android.com/google/play-services/id.html – sirvon

+0

मुझे com.google.android.gms.ads.identifier.AdvertisingIdClient.getAdvertisingIdInfo पर निम्न त्रुटि मिलती है: ** java.lang.No.SuchFieldError : android.content.pm.PackageInfo.signatures ** मैं इससे कैसे बच सकता हूं? – mdavid

-1

तक पहुँचने विज्ञापन आईडी केवल समर्थित विधि है सीधे Play सेवाएं एसडीके को जोड़ने और उन API के माध्यम से विज्ञापन आईडी पहुंच कर। Google किसी भी वर्कअराउंड की अनुशंसा या समर्थन नहीं करता है जो Play Services API पर सीधे पहुंच से बचाता है क्योंकि यह उपयोगकर्ता की कार्यक्षमता को तोड़ देता है (जैसे मामलों में त्रुटि प्रबंधन जहां डिवाइस पर Play Services ऐप पुराना है) और इसका व्यवहार भविष्य के Play के साथ अप्रत्याशित होगा सेवाएं रिलीज

Google Play Developer Program Policies की आवश्यकता है कि आप केवल Google Play API को अधिकृत तरीके से एक्सेस करें।

+0

धन्यवाद एरिक, यह जानना अच्छा है। हालांकि आपकी प्रतिक्रिया @ डोरर्स के 2 मुद्दों का समाधान प्रदान नहीं करती है और हम में से अधिकांश हैं। यदि कोई बेहतर दृष्टिकोण है तो कृपया हमें बताएं। – Adrian

1

MoPub और कुछ अन्य बड़े खिलाड़ी अपने एसडीके में जीपीएस शामिल नहीं हैं।

the MoPub SDK does not require Google Play Services. If you have it installed, we will automatically use the new Google Advertising ID. If you do NOT install Google Play Services, we will continue to pass the old Android ID. Note that all publishers need to use GPS in their app by August 1 to prevent their apps from being rejected by the Google Play Store

चेक एक बहुत अधिक विस्तार के लिए इस लिंक:

http://help.mopub.com/customer/portal/articles/1523610-google-advertising-id-faqs

आशा इस मदद करता है MoPub का सहायता पृष्ठ से।

6

नोट: मेरा जवाब अब के बाद से आप चुन सकते हैं जो GooglePlayServices पुस्तकालय के कुछ हिस्सों आप अपने प्रोजेक्ट में शामिल करना चाहते Gradle के लिए पुरानी हो चुकी है

जब परियोजना मैं पर काम कर रहा था पर पहुंच गया मैं हाल ही में एक ही समस्या में पड़ गए 65k डेक्स सीमा।

यहाँ कैसे मैं इसे हल है:

https://code.google.com/p/jarjar/downloads/list को
  • जाओ और .jar प्रारूप में नवीनतम जार जार लिंक डाउनलोड करें। फ़ाइल को एक कार्य फ़ोल्डर में रखें। इस उदाहरण के लिए मैं डेस्कटॉप का उपयोग करूंगा।

  • [एंड्रॉइड एसडीके पथ] \ extras \ google \ google_play_services \ libproject \ google-play-services_lib \ libs पर जाएं और उसी कार्य फ़ोल्डर में google-play-services.jar कॉपी करें।

  • उसी फ़ोल्डर में नियम.txt नामक एक टेक्स्ट फ़ाइल बनाएं (नाम वास्तव में कोई फर्क नहीं पड़ता)।

  • rules.txt पाठ (उद्धरण के बिना) पेस्ट के अंदर:

"keep com.google.android.gms.ads.identifier.AdvertisingIdClient"

  • आप अन्य वर्गों आप रखना चाहते हैं चाहते हैं, आप उन्हें यहाँ जोड़ सकते हैं।

  • कमांड प्रॉम्प्ट फ़ाइल खोलें और अपने कार्य फ़ोल्डर में पथ बदलें। विंडोज़ पर [सीडी] कमांड का उपयोग करें।

java -jar [jarjar archive] process [rulesFile] [inJar] [outJar]

  • आप JarJar लिंक आदेश और यहां नियमों के बारे में और अधिक जानकारी प्राप्त कर सकते हैं::

  • निम्न आदेश लिखें https://code.google.com/p/jarjar/wiki/CommandLineDocs

  • बस एक उदाहरण देने के लिए, आदेश मुझे लिखना था (इस तरह आपके फ़ाइल नामों के अनुसार बदलें):

java -jar jarjar-1.4.jar process rules.txt google-play-services.jar google-play-services-lite.jar

  • आदेश निष्पादित।

आईटी क्या करता है:

  • आदेश एक नया जावा संग्रह उत्पन्न होगा (* .jar) काम कर रहे फ़ोल्डर है कि केवल वर्ग से अपने विज्ञापनदाता आईडी और उसके निर्भरता प्राप्त करने के लिए की जरूरत में शामिल होंगे में। तो, गूगल प्ले-services.jar नीचे 2.2 एमबी से ~ को 50kb

इसका उपयोग कैसे जाना होगा: एसडीके से अपने प्रोजेक्ट में हमेशा की तरह

  • आयात Google Play सेवाओं इसे अपने कार्यक्षेत्र में कॉपी करना सुनिश्चित करें। Libs फ़ोल्डर में, google-play-services.jar को आपके द्वारा जेनरेट किए गए जार के साथ प्रतिस्थापित करें।

  • यदि आप वहां हैं, तो आप संसाधनों को भी 0.5 एमबी मुक्त करने के लिए हटा सकते हैं। मान/common_strings.xml और मान/version.xml रखना सुनिश्चित करें।

  • Google play सेवाओं के लिए मेनिफेस्ट मेटाडेटा जोड़ने के लिए मत भूलना।

यह मैं अधिक 2.5 एमबी के साथ इस परियोजना आकार को कम करने और 65k डेक्स वर्गों और तरीकों के तहत रहने के लिए सीमित कर, जबकि Google विज्ञापनदाता आईडी का उपयोग करने में सक्षम होने में मदद की।

आशा है कि यह आपकी भी मदद करेगा।

3

एड्रियन का समाधान उत्कृष्ट है, और मैं इसे स्वयं उपयोग करता हूं।

हालांकि, आज मैंने पाया कि डिवाइस पर Google Play Services इंस्टॉल नहीं होने पर यह एक बग है। आपकी गतिविधि/सेवा बंद होने पर आपको ServiceConnection लीक करने के बारे में एक संदेश मिलेगा। यह वास्तव में Context.bindService में एक बग है: जब सेवा के लिए बाध्यकारी विफल हो जाता है (इस मामले में क्योंकि Google Play सेवाएं स्थापित नहीं हैं), Context.bindService झूठी रिटर्न देता है, लेकिन यह ServiceConnection के संदर्भ को साफ़ नहीं करता है, और उम्मीद है कि आप Context.unbindService पर भी कॉल करें हालांकि सेवा मौजूद नहीं है!

public static AdInfo getAdvertisingIdInfo(Context context) throws Exception { 
    if(Looper.myLooper() == Looper.getMainLooper()) 
     throw new IllegalStateException("Cannot be called from the main thread"); 

    try { 
     PackageManager pm = context.getPackageManager(); 
     pm.getPackageInfo("com.android.vending", 0); 
    } catch(Exception e) { 
     throw e; 
    } 

    AdvertisingConnection connection = new AdvertisingConnection(); 
    Intent intent = new Intent("com.google.android.gms.ads.identifier.service.START"); 
    intent.setPackage("com.google.android.gms"); 
    try { 
     if(context.bindService(intent, connection, Context.BIND_AUTO_CREATE)) { 
      AdvertisingInterface adInterface = new AdvertisingInterface(connection.getBinder()); 
      AdInfo adInfo = new AdInfo(adInterface.getId(), adInterface.isLimitAdTrackingEnabled(true)); 
      return adInfo; 
     } 
    } catch(Exception exception) { 
     throw exception; 
    } finally { 
     context.unbindService(connection); 
    } 
    throw new IOException("Google Play connection failed"); 
} 

इस तरह Context.unbindService भले ही Context.bindService रिटर्न false बुलाया जाएगा:

वैकल्पिक हल इस तरह getAdvertisingIdInfo के कोड को बदलने के लिए है।