2013-04-28 11 views
6

का अधिकार सेट करें शायद शीर्षक थोड़ा भ्रामक है। मेरी समस्या यह है कि मेरे पास एक एंड्रॉइड लाइब्रेरी प्रोजेक्ट है जो दो मानक एंड्रॉइड प्रोजेक्ट्स के बीच साझा किया जाता है: एक ऐप के एक मुफ्त संस्करण के लिए और दूसरा भुगतान किए गए संस्करण के लिए। लाइब्रेरी में वर्तमान में एक सामग्री प्रदाता के लिए कोड है, जिसमें यूआरआई और कॉलम नाम जैसी चीजों के लिए कई स्थिर स्ट्रिंग चर के साथ अनुबंध वर्ग शामिल है। अब मैं यूआरआई को पुस्तकालय का उपयोग कर रहा है, इस पर निर्भर करता है कि यूआरआई के लिए "प्राधिकरण" बदलना है। एक समाधान जो दिमाग में आता है वह एक स्ट्रिंग संसाधन के रूप में प्राधिकरण को संग्रहीत कर रहा है और उस स्ट्रिंग को स्थिर अंतिम स्ट्रिंग चर में रन-टाइम पर लोड कर रहा है। हालांकि, मुझे यकीन नहीं है कि यह कैसे करें क्योंकि अनुबंध वर्ग को एक निजी कन्स्ट्रक्टर और स्ट्रिंग संसाधन लोड करने के लिए कोई संदर्भ वस्तु नहीं है। मेरी समस्या को हल करने के लिए अन्य विकल्प क्या उपलब्ध हैं?गतिशील रूप से एक ContentProvider

+0

क्या आप मेरा जवाब जांचने की देखभाल करते हैं और मुझे बताते हैं कि क्या यह आपके प्रश्न का उत्तर देता है या यदि कुछ गड़बड़ है? –

+0

@EmanuelMoecklin मैंने आपके ए को अपरिवर्तित किया लेकिन मेरे पास इस ऐप से खेलने के लिए समय नहीं था क्योंकि यह एक प्रश्नोत्तरी ऐप है और काम चल रहा है ;-(मेरे पास एक बार जवाब होगा यह पता लगाने का एक मौका है कि कौन सा सबसे उपयोगी है। –

उत्तर

6

उपयोगकर्ता के लिए दोनों संस्करणों को स्थापित करने का प्रयास करने पर स्वतंत्र और भुगतान संस्करण के लिए विभिन्न अधिकारियों का उपयोग करना समझ में आता है। मैं बहुत की तरह प्रकट में दो संस्करण के लिए एक अलग प्राधिकरण को परिभाषित कर रहा हूँ:

<provider 
    android:name="MyApp.MyProvider" 
    android:authorities="MyApp.MyProvider.free" 
    android:grantUriPermissions="true"/> 

तो मैं एक xml फ़ाइल (मैं एक विशेष config.xml फ़ाइल का उपयोग में प्रदाता कॉन्फ़िगर क्योंकि मैं की तरह अधिक विन्यास डेटा है प्रदाता अधिकार है, लेकिन आप निश्चित रूप से strings.xml उपयोग कर सकते हैं):

<string name="my_provider_authority">MyApp.MyProvider.free</string> 

कोड किसी अन्य स्ट्रिंग संसाधन के रूप में प्रदाता प्राधिकार प्राप्त करता है। किसी संदर्भ के बिना स्ट्रिंग संसाधनों तक पहुंचने के लिए एप्लिकेशन संदर्भ का उपयोग करें।

public class MyApplication extends Application { 
    private static Context sContext; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     sContext = this; 
    } 

    public static Context getContext() { 
     return sContext; 
    } 
} 
बेशक

आप अपने मेनिफ़ेस्ट में MyApplication परिभाषित करने की जरूरत: मैं अपने एप्लिकेशन में कहीं से आवेदन संदर्भ का उपयोग करने की एक आवेदन वर्ग का उपयोग कर रहा (इसमें दो अपवाद यद्यपि कर रहे हैं)। यह आपको अपने ऐप में कहीं से भी स्ट्रिंग और अन्य संसाधनों तक पहुंचने की अनुमति देता है। हालांकि दो अपवाद हैं:

  1. सामग्री प्रदाता। एप्लिकेशन प्रारंभ होने से पहले सामग्री प्रदाता प्रारंभ किए जा सकते हैं और इसलिए आपके पास कोई एप्लिकेशन संदर्भ उपलब्ध नहीं होगा। हालांकि यह कोई समस्या नहीं है क्योंकि ContentProviders getContext() के माध्यम से अपना स्वयं का संदर्भ प्राप्त करते हैं।
  2. स्टेटिक कोड: संदर्भ एंड्रॉइड घटकों के जीवन चक्र (गतिविधियां, टुकड़े, ब्रॉडकास्ट रिसीवर, सेवाएं इत्यादि) के बाहर उपलब्ध नहीं हो सकता है। आवेदन संदर्भ पर निर्भर स्टेटिक प्रारंभकर्ता इसलिए एक अच्छा विचार नहीं हैं। लेकिन यह भी एक वास्तविक मुद्दा नहीं है क्योंकि एंड्रॉइड घटकों के जीवन चक्र के बाहर एक संदर्भ का उपयोग करने की अनुमति नहीं है और किसी संदर्भ को प्राप्त करने वाली स्थिर विधियों को हमेशा उस जीवन चक्र के भीतर से बुलाया जाएगा। जैसे अगर किसी गतिविधि को ContentProvider के अधिकार को जानने की आवश्यकता है तो यह आपके अनुबंध वर्ग में एक स्थिर विधि को कॉल करेगा और वह कॉल गतिविधि की ONXYZ() विधियों में से एक होगा जैसे क्रेट() या ऑनस्टार्ट() जो सुनिश्चित करेगा कि संदर्भ प्रारंभ किया गया है । तो आपको बस इतना करना है कि आलसी आपके अनुबंध वर्ग में चर शुरू करें और सुनिश्चित करें कि कॉलर केवल चर को पुनर्प्राप्त करता है जब यह स्पष्ट हो जाता है कि Application.onCreate() को पहले कॉल किया गया है। निश्चित रूप से एक गतिविधि के भीतर से आप सीधे स्ट्रिंग संसाधनों को पुनर्प्राप्त कर सकते हैं।जब आपको अन्य वर्गों/वस्तुओं में संसाधनों की आवश्यकता होती है तो मेरी विधि का वास्तविक लाभ स्पष्ट हो जाएगा। ये ऑब्जेक्ट्स अभी भी कुछ एंड्रॉइड घटक के जीवन चक्र से बंधे रहेंगे, लेकिन आपको इन सभी ऑब्जेक्ट्स के संदर्भ में चारों ओर गुजरना पड़ेगा, जो 1) बहुत बोझिल है और 2) बहुत ही त्रुटि प्रवण है जब संदर्भ को लीक करने की बात आती है स्मृति उपयोग के मुद्दों (Android ऐप्स के साथ सबसे आम समस्याओं में से एक) का कारण बन सकता है।
+0

सुझावों के लिए धन्यवाद। मुझे लगता है कि एक आवेदन बनाना subclass जाने के रास्ते की तरह लगता है। जब मैं अपने "अनुबंध" वर्ग में एक स्थिर प्रारंभकर्ता से 'MyApplication.getContext() 'को कॉल करता हूं, तो मुझे किस मुद्दे के बारे में पता होना चाहिए? इसके अलावा, क्या आप' @ स्ट्रिंग/my_provider_authority' 'android: अधिकारियों की विशेषता में डुप्लिकेशंस को कम करने के लिए? –

+0

मैंने एक स्थिर प्रारंभकर्ता में अनुप्रयोग संदर्भ का उपयोग करने के बारे में आपकी चिंताओं को हल करने के लिए अपना उत्तर संशोधित किया। इसका जवाब मूल रूप से आलसी होना है जो एक स्ट्रिंग संसाधन से पढ़े गए चर को प्रारंभ करता है और यह सुनिश्चित करने के लिए कि आप एप्लिकेशन जीवन चक्र के बाहर से गेटटर विधियों को कॉल न करें। –

+2

इस उत्तर के अनुसार: http://stackoverflow.com/q/6461776/534471 आपको प्रदाता के अधिकार को परिभाषित करने के लिए @string संदर्भ का उपयोग नहीं करना चाहिए, लेकिन आप (कम से कम एंड्रॉइड संस्करण 2.1 में) कर सकते हैं। लेकिन मैं वहां जवाब से सहमत हूं कि यह खतरनाक है और शायद इसे छोड़ दिया जाना चाहिए। –

0

अधिकार क्यों बदलते हैं? आपको प्रदाता को निर्यात करने की आवश्यकता नहीं है, जिसका अर्थ यह है कि ऐप को डीकोनस्ट्रक्चर के अलावा कोई भी प्राधिकरण नाम भी नहीं देख सकता है। फिर भी, वे प्रदाता तक पहुंचने में सक्षम नहीं होंगे।

यदि यह आपकी आंतरिक सुविधा के लिए है, तो मैं उसी प्राधिकारी का उपयोग करता हूं लेकिन यूआरआई पर अलग-अलग सुरक्षा डालता हूं।

संक्षेप में, आपका विचार दिलचस्प है, लेकिन मैं इसे इस तरह से नहीं करूँगा। एक गड़बड़ का बहुत अधिक।

+0

यदि उपयोगकर्ता के दोनों संस्करणों को स्थापित किया गया तो क्या होगा? –

+0

मुफ्त संस्करण भी एकमात्र प्रदाता का खुलासा करता है ताकि भुगतान किए गए संस्करण को मौजूदा डेटा आयात करने की अनुमति मिल सके। आखिरकार, दोनों में प्रदाता मुफ्त और भुगतान किए गए संस्करणों को एक कर्सर लोडर द्वारा आंतरिक रूप से उपयोग किया जाएगा। अगर मैं सही ढंग से समझता हूं, तो मुझे बाद में उपयोग के मामले के लिए टैग की आवश्यकता नहीं है क्योंकि यह प्रत्येक ऐप के लिए आंतरिक है। –

11

बिल्ड टूल्स के नए संस्करणों का उपयोग करने वालों के लिए यहां एक बेहतर समाधान है: प्राधिकरण को अपने पैकेज नाम से संबंधित बनाएं। आप इसे ${applicationId} का उपयोग करके स्वचालित रूप से कर सकते हैं, जिसे बिल्ड प्रक्रिया के दौरान आपके ऐप के पैकेज नाम में विस्तारित किया गया है।

<provider 
    android:name=".MyContentProvider" 
    android:authorities="${applicationId}.provider"/> 

मान लें कि आपका पैकेज के नाम com.example.app.paid और com.example.app.free हैं। जब आप अपना ऐप बनाते हैं, तो प्राधिकरण com.example.app.paid.provider और com.example.app.free.provider बन जाएगा, संगत रूप से।

अपने कोड में प्रदाता प्राधिकरण का संदर्भ देने के लिए, BuildConfig.APPLICATION_ID + ".provider" का उपयोग करें।

+0

Android स्टूडियो और ग्रेडल बिल्ड श्रृंखला द्वारा प्रदान की गई सुविधाओं पर अपडेट के लिए धन्यवाद। –

+0

इसके अतिरिक्त, मैं भुगतान ऐप से निःशुल्क ऐप के प्रदाता का संदर्भ कैसे दूंगा। यह दो अलग-अलग प्रदाताओं के मुख्य कारणों में से एक है। जब उपयोगकर्ता सशुल्क ऐप खरीदता है, तो मुझे मुफ्त ऐप से डेटा आयात करने में सक्षम होना चाहिए। –

+0

@ कोड-अपरेंटिस मानक अभ्यास एक इन-एप खरीद का भुगतान अपग्रेड करना है, ताकि आप एक ही प्रदाता का उपयोग जारी रख सकें। वैकल्पिक रूप से, आप अपने प्रदाता को 'android: exported =" true "' के रूप में चिह्नित कर सकते हैं, जो आपके प्रदाता डेटा को अन्य ऐप्स द्वारा पढ़ने की अनुमति देता है (अनुमतियां जोड़ने के लिए याद रखें ताकि केवल आपका ऐप इसे पढ़ सके!) –

संबंधित मुद्दे