2012-06-14 21 views
17

मैं थोड़ी देर के लिए इसके साथ संघर्ष कर रहा हूं। असल में, मैं दो प्राथमिकताएं (जो हमेशा एक साथ स्थापित की जाएंगी) साझा प्राथमिकताएं चाहते हैं, उनमें से एक केवल पृष्ठभूमि में चलती है और प्राथमिकताओं का उपयोग करने की आवश्यकता होती है (वरीयताओं का स्वामित्व होना चाहिए, लेकिन केवल वास्तव में की आवश्यकता है उन्हें पढ़ें) और दूसरा ऐप फ्रंट-एंड यूआई ऐप है जिसे अन्य ऐप के स्वामित्व वाली प्राथमिकता फ़ाइल में लिखने में सक्षम होना चाहिए। सेवा पृष्ठभूमि में चीजें कर रही है (जो वरीयताओं द्वारा निर्धारित की जा सकती है) और यूआई उपयोगकर्ता को वरीयताओं को संपादित करने और सेवा से कुछ जानकारी देखने की अनुमति देगा। हालांकि, वे अलग-अलग पैकेज/ऐप्स होंगे।मैं दो अलग-अलग एंड्रॉइड ऐप्स में एक साझाप्रणाली फ़ाइल कैसे साझा कर सकता हूं?

मैं निम्नलिखित this tutorial जो मुझे कैसे एक ऐप्लिकेशन में वरीयताओं जो किसी अन्य के द्वारा पढ़ा जा सकता है के लिए बहुत बढ़िया सुझाव दिया की कोशिश की। अनिवार्य रूप से, मैं myContext = createPackageContext("com.example.package",Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE); के माध्यम से एक नया संदर्भ बनाता हूं और फिर myContext.getSharedPreferences("pref_name", Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE); पर कॉल करता हूं हालांकि, मैं बाहरी ऐप से सफलतापूर्वक वरीयताओं को नहीं लिख सकता - (SharedPreferences.Editor) .commit() झूठी रिटर्न देता है और मुझे असमर्थ होने के बारे में लॉगकैट में चेतावनी मिलती है pref_name.xml.bak को संपादित करने के लिए।

मैं कैसे सफलतापूर्वक तो उन दोनों को पढ़ने के लिए और एक ही प्राथमिकताएं फ़ाइल (जो उन में से एक का डेटा फ़ोल्डर में संग्रहीत किया जाता है) को लिख सकते हैं मेरी अनुप्रयोगों स्थापित कर सकते हैं?

+0

क्यों, जब आप कहते हैं कि ये हमेशा एक साथ स्थापित होते हैं, तो क्या इन्हें दो अलग-अलग ऐप्स होने की आवश्यकता है? बहुत सारे सिरदर्द की तरह लगता है, इसलिए संभवतः आप एक लाभ की कल्पना कर रहे हैं, लेकिन मुझे आश्चर्य है कि वास्तव में अलग-अलग ऐप्स होने के बिना इसे प्राप्त करने का कोई तरीका हो सकता है। –

+2

मैं दोनों ऐप्स इंस्टॉल करने, वरीयताओं को सेट करने में सक्षम होना चाहता था, और उसके बाद फ्रंटएंड यूआई को अनइंस्टॉल करना चाहता था लेकिन सेवा को पृष्ठभूमि में जाने देना था। यह मुझे दोबारा इंस्टॉल किए बिना एक ऐप को अपग्रेड करने की अनुमति देता है। यह निश्चित रूप से _necessary_ नहीं है (और मैं इसका भी उपयोग नहीं कर सकता) लेकिन यह मेरे द्वारा डिजाइन किए जाने के तरीके को लागू करने के लिए मेरे विचारों में से एक था। – matt5784

उत्तर

6

सबसे पहले, मुझे ध्यान रखना चाहिए कि यह आधिकारिक रूप से समर्थित नहीं है, हालांकि भविष्य में एंड्रॉइड में जोड़ा जाने वाला एक समर्थित तरीका हो सकता है (दोनों दावों के लिए स्रोत: दूसरे पैराग्राफ देखें this link)।

फिर, यह समर्थित नहीं है और बहुत संभवतः अस्थिर है। मैंने मुख्य रूप से यह प्रयोग करने के लिए यह प्रयोग किया कि यह संभव था या नहीं; यदि आप वास्तव में इस विधि को किसी एप्लिकेशन में शामिल करने की योजना बना रहे हैं तो अत्यधिक सावधानी बरतें।

हालांकि, यह अनुप्रयोगों के बीच वरीयताओं साझा करने के लिए अगर कुछ शर्तों के पूरा होने संभव प्रतीत होता है। सबसे पहले, यदि आप एप बी को ऐप ए की प्राथमिकताओं तक पहुंचने में सक्षम होना चाहते हैं तो ऐप बी का पैकेज नाम ऐप ए के पैकेज नाम का एक बच्चा होना चाहिए (उदा। ऐप ए: com.example.pkg ऐप बी: com.example.pkg.stuff)। इसके अतिरिक्त, वे एक ही समय में फ़ाइल तक पहुंच नहीं ले सकते हैं (मुझे लगता है कि समान नियम लागू होते हैं क्योंकि गतिविधियों के बीच उन्हें एक्सेस करने के लिए, यदि आप परमाणु पहुंच सुनिश्चित करना चाहते हैं तो आपको अतिरिक्त सुरक्षा जैसे कि .wait () और .notify(), लेकिन मैं उसमें नहीं जाऊंगा)।

नोट: यह सभी 2.2 और 2.3.3 पर एमुलेटर पर काम करता है- मैंने उपकरणों या एंड्रॉइड संस्करणों में बड़े पैमाने पर परीक्षण नहीं किया है।




हालात एप्लिकेशन जो (ऊपर की ओर से एप्लिकेशन ए) वरीयताओं ही जा रहा है में करने के लिए:)

1. घोषित SharedPreferences फ़ाइल
यह काफी सरल है । बस अपनी साझाpreferences फ़ाइल और अपनी कक्षा में संपादक के लिए कुछ चर घोषित करें और उन्हें अपने ऑनरेट विधि में तुरंत चालू करें। आप अब वरीयताओं में एक स्ट्रिंग डाल सकते हैं जिसका उपयोग आप यह सुनिश्चित करने के लिए करेंगे कि अन्य ऐप इसे ठीक से पढ़ सके।

public class stuff extends Activity { 
    SharedPreferences mPrefs = null; 
    SharedPreferences.Editor mEd= null; 
    @Override 
    public void onCreate(Bundle savedInstanceState){ 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     mPrefs = (getApplicationContext()).getSharedPreferences("svcprefs", Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE); 
     mEd = mPrefs.edit(); 
     mEd.putString("test", "original send from prefs owner"); 
     mEd.commit(); 

2.) बैकअप फ़ाइल getSharedPreferences विधि से प्राथमिकताएं लोड करने में एक .bak फ़ाइल के लिए जाँच करने के लिए प्रकट होता है सेट करें।यही कारण है कि यह प्रलेखन में कहता है कि यह कई प्रक्रियाओं में काम नहीं करेगा; I/O को कम करने के लिए, जब आप उन्हें पकड़ते हैं तो यह एक बार prefs लोड करता है और जब आप अपना एप्लिकेशन/गतिविधि बंद करते हैं तो केवल उन्हें वापस ले जाता है। हालांकि, अगर आप इसे किसी बाहरी एप्लिकेशन से कॉल करते हैं तो आपको फ़ोल्डर के लिए सही फ़ाइल अनुमतियां नहीं होने के बारे में चेतावनी मिलेगी (जो कि पहला ऐप का डेटा फ़ोल्डर है)। इसे ठीक करने के लिए हम खुद को .bak फ़ाइल बनाने जा रहे हैं और इसे सार्वजनिक रूप से पठनीय/लिखने योग्य बनाते हैं। जिस तरह से मैंने इसे चुना है वह मेरी समग्र कक्षा में तीन चर परिभाषित करना था।

final String[] copyToBackup = { "dd", "if=/data/data/com.example.pkg/shared_prefs/prefs.xml", "of=/data/data/com.example.pkg/shared_prefs/prefs.xml.bak", "bs=1024" }; 
final String[] mainFixPerm = {"chmod", "666", "/data/data/com.example.pkg/shared_prefs/prefs.xml"}; 
final String[] bakFixPerm = {"chmod", "666", "/data/data/com.example.pkg/shared_prefs/prefs.xml.bak"}; 

और अपने मुख्य वर्ग में एक समारोह जो तर्क के रूप में इन लेते हैं और उन्हें

public void execCommand(String[] arg0){ 
    try { 
     final Process pr = Runtime.getRuntime().exec(arg0); 
     final int retval = pr.waitFor(); 
     if (retval != 0) { 
      System.err.println("Error:" + retval); 
     } 
    } 
    catch (Exception e) {} 
} 

निष्पादित यह बहुत सुंदर या अच्छा नहीं है, लेकिन यह काम करता है होगा बनाते हैं। अब, आपके ऑनक्रेट विधि में (editor.commit() के ठीक बाद) आप इस फ़ंक्शन को तीनों तारों में से प्रत्येक के साथ कॉल करेंगे।

execCommand(copyToBackup); 
execCommand(mainFixPerm); 
execCommand(bakFixPerm); 

इस फ़ाइल को कॉपी करें और दोनों मुख्य .xml और बाहर कार्यक्रमों के लिए सुलभ .xml.bak फ़ाइलों कर देगा। यह सुनिश्चित करने के लिए कि इन्हें आपके ऐप से बाहर निकलने पर डेटाबेस का बैक अप ठीक से बैक अप किया गया है, और अतिरिक्त रूप से उन्हें कॉल करने से पहले उन्हें सही तरीके से कॉल करें (अन्यथा यह .bak फ़ाइल लोड करेगा यदि कोई अन्य प्रक्रिया मुख्य .xml फ़ाइल को संपादित कर रही है तो संभवतः पुराना है)। हालांकि, इस एप्लिकेशन में आपको बस इतना करना है। आप इस गतिविधि में कहीं और getSharedPreferences को कॉल कर सकते हैं और यह .xml फ़ाइल से सभी डेटा ले जाएगा, जिससे आप getdatatype ("key") विधियों को कॉल कर सकते हैं और इसे पुनर्प्राप्त कर सकते हैं।


चीजें (ऊपर की ओर से एप्लिकेशन बी) एक्सेस फ़ाइल (फ़ाइलें) में करने के लिए

1.) फ़ाइल
लिखें यह भी सरल है। मैंने इस गतिविधि पर एक बटन बनाया और इसके ऑनक्लिक विधि में कोड सेट किया जो साझा प्राथमिकता फ़ाइल में कुछ सहेज लेगा। याद रखें कि ऐप बी का पैकेज ऐप ए के पैकेज का बच्चा होना चाहिए। हम ऐप ए के संदर्भ के आधार पर एक संदर्भ तैयार करेंगे और फिर उस संदर्भ पर getSharedPreferences को कॉल करेंगे।

prefsbutton.setOnClickListener(new View.OnClickListener() { 
    public void onClick(View v) { 
     Context myContext = null; 
     try { 
      // App A's context 
      myContext = createPackageContext("com.example.pkg", Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE); 
     } catch (NameNotFoundException e) {e.printStackTrace();} 

     testPrefs = myContext.getSharedPreferences("svcprefs", Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE); 
     testEd = testPrefs.edit(); 
     String valueFromPrefs = testPrefs.getString("test", "read failure"); 
     TextView test1 = (TextView)findViewById(R.id.tvprefs); 
     test1.setText(valueFromPrefs); 
     testEd.putString("test2", "testback"); 
     boolean edit_success = testEd.commit(); 

इस स्ट्रिंग मैं अन्य अनुप्रयोग में सेट पकड़ लेता है और इस आवेदन में एक TextView में यह (या एक त्रुटि संदेश) प्रदर्शित करता है। इसके अतिरिक्त यह प्राथमिकता फ़ाइल में एक नई स्ट्रिंग सेट करता है और परिवर्तन करता है। इस रन के बाद, यदि आपका अन्य एप्लिकेशन कॉल शेर किया गया है, तो यह इस ऐप के परिवर्तन सहित फ़ाइल को पुनर्प्राप्त करेगा।

+2

"हालांकि यह भविष्य में हो सकता है" - कमांड लाइन बाइनरी का उपयोग एंड्रॉइड एसडीके में कभी भी समर्थित नहीं होगा। निजी तौर पर, मैं इस तकनीक को 10-मीटर ध्रुव के साथ नहीं छूंगा। यदि आप ऐप्स के बीच डेटा साझा करना चाहते हैं, तो एक वास्तविक एपीआई का उपयोग करें, जैसे 'ContentProvider' को कार्यान्वित करना जो आपके' साझा किए गए संदर्भ 'द्वारा समर्थित है। – CommonsWare

+0

मैं भविष्यवाणी नहीं कर सका कि एंड्रॉइड टीम क्या करेगी (सिवाय इसके कि जब वे मुझे बताएंगे)। हालांकि, मैं ** ** ** निश्चित हूं कि अगर उन्होंने इसे कार्यान्वित किया तो यह बहुत साफ होगा और 'डीडी' या 'chmod' चलाने की आवश्यकता नहीं होगी। वास्तव में, यह किसी अन्य तकनीक के माध्यम से भी संभव हो सकता है - और यदि मुझे उम्मीद है कि कोई जवाब पोस्ट करेगा। यह वही तरीका है जो मुझे काम करने के लिए मिला। – matt5784

+0

क्या दो ऐप्स के लिए समान साझाprefrences पर डेटा लिखना संभव है? –

34

फ़ाइल के लिए निजी मोड सेट करना बेहतर है। इस फ़ाइल को साझा करने के लिए ऐप को प्रमाण पत्र के उसी सेट के साथ हस्ताक्षर करने की आवश्यकता है।

दोनों ऐप्स में साझा यूज़र आईडी सेट करें। अन्य पैकेज से

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
package="com.example.hello" 
android:versionCode="1" 
android:versionName="1.0" 
android:sharedUserId="com.example"> 
.... 

प्राप्त प्रसंग:

mContext = context.createPackageContext(
         "com.example.otherapp", 
         Context.MODE_PRIVATE); 
mPrefs = mContext.getSharedPreferences("sameFileNameHere", Activity.MODE_PRIVATE); 

SharedPreference से हमेशा की तरह आइटम प्राप्त करें। अब आप इसका उपयोग कर सकते हैं।

+2

यह सुनिश्चित नहीं है कि यह स्वीकार्य उत्तर क्यों नहीं है। ऐसा करने का यह सही तरीका है, और बेकार ढंग से काम करता है। –

+1

आपको 'Context.CONTEXT_RESTRICTED' के साथ' Context.MODE_PRIVATE' को प्रतिस्थापित करना पड़ सकता है। –

+0

हालांकि, इसे लागू करना आसान है, दुर्भाग्यवश, यदि आप विकास के बाद के कुछ चरणों में इसे जोड़ते हैं, तो आपके ऐप को अपग्रेड करना काम नहीं करेगा (आपको पुनर्स्थापित करना होगा)। इसके अतिरिक्त, यदि आप इन-ऐप बिलिंग का उपयोग करते हैं, तो यह काम करने की संभावना नहीं है। – lenooh

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