2012-03-09 13 views
42

मैं एंड्रॉइड मार्केट के बाहर वितरित किए जा रहे लोगों के लिए a library to allow apps to self-update पर काम कर रहा हूं।क्या हम एक सामग्री प्रदाता से एपीके स्थापित कर सकते हैं?

मेरे मूल योजना कोड है कि आंतरिक भंडारण के लिए APK फ़ाइल डाउनलोड होगा, और फिर एक ContentProvider और एक content://Uri के माध्यम से वहां से इसे स्थापित शामिल करने के लिए किया गया था। हालांकि, जब मैंने कोशिश की, तो इंस्टॉलर सिस्टम ने LogCat को "छोड़ने dir:" चेतावनी डाली और वास्तव में इसे इंस्टॉल करने में विफल रहा। एक बार जब मैंने एपीके को बाहरी स्टोरेज में डाउनलोड करने और file://UriACTION_VIEW इंस्टॉलर Intent के साथ स्विच करने के लिए स्विच किया, तो यह काम करता था।

"छोड़ा जा रहा है dir:" संदेश PackageParser में parsePackage() से लॉग इन करने की है, जो मानते हैं कि यह एक File साथ काम कर रहा है लगता है लगता है। इससे पता चलता है कि हम content://Uri मानों का उपयोग नहीं कर सकते हैं।

किसी को भी सफलतापूर्वक एक application/vnd.android.package-archiveIntent एक content://Uri साथ पर ACTION_VIEW इस्तेमाल किया गया है? यदि हां, तो क्या ContentProvider स्थापित करने में कुछ विशिष्ट चाल थी जिसने इसे काम किया?

धन्यवाद!

+0

और यह सामग्रीप्रोवाइडर कितना उत्साहजनक रूप से दिखता है (विशेष रूप से खुलाफाइल कार्यान्वयन)? – Selvin

+1

@ सेल्विन: 'ओपनफाइल() 'कार्यान्वयन के साथ एक' ContentProvider 'फाइलों को सेवा करने की अनुमति देने के लिए आवश्यक है, और मैंने [एक मौजूदा मामूली कार्यान्वयन जिसे मैं सामान्य रूप से जानता हूं) का उपयोग करता है (https://github.com/ आधार के रूप में commonsguy/cw-advandroid/पेड़/मास्टर/सामग्री प्रदाता/फ़ाइलें)। मेरा सवाल यह है कि क्या किसी ने इसे सफलतापूर्वक काम करने के लिए प्राप्त किया है, क्योंकि स्रोत कोड के मेरे पढ़ने से पता चलता है कि यह समर्थित नहीं है, भले ही 'ContentProvider' जैसा दिखता हो। – CommonsWare

+0

मैंने इसे आजमाया नहीं है, लेकिन आपने यहां वर्णित विधि देखी है: http://stackoverflow.com/a/4605040/377260 –

उत्तर

12

मुझे लगता है कि यह संभव नहीं है, क्योंकि जावा एपीआई इसे अनुमति नहीं देता है। ContentProvider's openFile()ParcelFileDescriptor देता है, जिससे आप java.io.FileDescriptor प्राप्त कर सकते हैं। इसके बाद आप या FileOutputStream खोलने के लिए इस FileDescriptor का उपयोग कर सकते हैं। दुर्भाग्यवश, आप इसे RandomAccessFile खोलने के लिए उपयोग नहीं कर सकते हैं (इस तथ्य के बावजूद कि RandomAccessFile अन्य लोगों के समान ही वर्णनकर्ताओं पर काम करता है, आपको जिस कन्स्ट्रक्टर की आवश्यकता होगी वह सिर्फ एपीआई से गायब है)।

एपीके फाइलें ज़िप फाइलें हैं, जिन्हें ऑर्डर से बाहर पढ़ा जाना चाहिए (आपको फ़ाइल निर्देशिका खोजने के लिए अंत करना है), मुझे लगता है कि स्थापना के कार्यान्वयन के लिए RandomAccessFile की आवश्यकता होगी, इसलिए यह नहीं होता उस मामले का समर्थन करना संभव है जिसे आप कार्यान्वित करने का प्रयास कर रहे हैं।

+1

मैं आपके मूल्यांकन से सहमत हूं, लेकिन जब आपका विश्लेषण मेरे मुकाबले एक अलग रास्ता नीचे चला गया है, तब भी यह काफी सुंदर है जहां मैं हूं - "ठीक है, यह * संभव * नहीं दिखता है"। मैं कुछ और अधिक निश्चित के लिए बाहर पकड़ रहा हूँ। :-) मैं आपका जवाब स्वीकार करूंगा, हालांकि, अगर मुझे कुछ बेहतर नहीं मिलता है। धन्यवाद! – CommonsWare

+0

पैकेज मैनेजर सेवा जो इंस्टॉलेशन को संभालती है वह एपीके फ़ाइल की एक प्रति बनाता है और इसलिए मूल यूआरआई को मांग क्षमता के साथ स्ट्रीम प्रदान करने की आवश्यकता नहीं होती है। –

+0

मैंने सामग्री प्रदाता के माध्यम से ज़िपों के अंदर पढ़ा है (मैं अपनी परियोजनाओं में से एक के लिए एडॉन्स डाउनलोड करता हूं और उनमें सामग्री प्रदाता द्वारा प्रदान की गई ज़िप शामिल है)। – HaMMeReD

6

मैं जूल्स विश्लेषण से सहमत हैं, और मैं ठोस precisions जोड़ना होगा:

PackageInstallerActivity में, जो एक apk पर ACTION_VIEW से पुकारा जाता है, वहाँ onCreate() विधि में यह है:

315 String apkPath = mPackageURI.getPath(); 
316 File apkFile = new File(apkPath); 

और से पहले कि, PackageUtil से इस विधि कहा जाता है:

73 public static PackageParser.Package getPackageInfo(Uri packageURI) { 
74  final String archiveFilePath = packageURI.getPath(); 
75  PackageParser packageParser = new PackageParser(archiveFilePath); 
76  File sourceFile = new File(archiveFilePath); 
77  DisplayMetrics metrics = new DisplayMetrics(); 
78  metrics.setToDefaults(); 
79  return packageParser.parsePackage(sourceFile, archiveFilePath, metrics, 0); 
80 } 

सभी इस बात की पुष्टि करने PackageManager है कि आदत ही उम्मीद फाइल यूरिस

आपके पास लॉग है, packageParser.parsePackage में पाया गया है, जो परीक्षण करता है कि उरी में दिया गया पथ एक फ़ाइल है या नहीं।

1

मैं अपने अनुप्रयोगों में से एक है जो मुझे स्थानीय भंडारण के लिए उपयोग की अनुमति देता है में इस राशि (उपयोगकर्ता वरीयता चयन आप मुझ पर एक जाना है से पहले;))

import java.io.*; 
import android.content.*; 
import android.database.*; 
import android.net.*; 
import android.os.*; 
import android.preference.PreferenceManager; 
import android.util.Log; 

public class LocalFileContentProvider extends ContentProvider { 
    private static final String URI_PREFIX = "content://your.content.provider.as.per.manifest"; 

    public static String constructUri(String url) { 
     Uri uri = Uri.parse(url); 
     return uri.isAbsolute() ? url : URI_PREFIX + url; 
    } 

    @Override 
    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { 

     SharedPreferences app_preferences = PreferenceManager.getDefaultSharedPreferences(getContext()); 

     boolean allowLocal = app_preferences.getBoolean("allowLocalFiles", false); 

     if (allowLocal) {  
      try { 
       File file = new File(uri.getPath()); 

       if (file.isDirectory()) 
        return null; 

       ParcelFileDescriptor parcel = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); 
       return parcel; 
      } catch (Exception e) { 
       return null; 
      } 
     } else { 
      return null; 
     } 

    } 

    @Override 
    public boolean onCreate() { 
     return true; 
    } 

    @Override 
    public int delete(Uri uri, String s, String[] as) { 
     throw new UnsupportedOperationException("Not supported by this provider"); 
    } 

    @Override 
    public String getType(Uri uri) { 
     throw new UnsupportedOperationException("Not supported by this provider"); 
    } 

    @Override 
    public Uri insert(Uri uri, ContentValues contentvalues) { 
     throw new UnsupportedOperationException("Not supported by this provider"); 
    } 

    @Override 
    public Cursor query(Uri uri, String[] as, String s, String[] as1, String s1) { 
     throw new UnsupportedOperationException("Not supported by this provider"); 
    } 

    @Override 
    public int update(Uri uri, ContentValues contentvalues, String s, String[] as) { 
     throw new UnsupportedOperationException("Not supported by this provider"); 
    } 

} 

मेरे प्रकट

<provider android:name="it.automated.android.kiosk.se.LocalFileContentProvider" 
     android:authorities="it.automated" /> 

शामिल और फिर इंस्टॉल (या एक्शन) शुरू करने के लिए

Intent viewIntent = new Intent(Intent.ACTION_VIEW); 
viewIntent.setDataAndType(Uri.parse(url), mimeType); 
+0

मैं फिर से कोशिश करूंगा। आपका कोड लगभग जो मैंने शुरू किया उसके समान है, जो प्रश्न में वर्णित परिणामों के साथ असफल रहा। धन्यवाद! – CommonsWare

+0

समस्या प्रदाता पक्ष पर नहीं है, इसलिए यदि आपने API डेमो कोड (http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/content/FileProvider का उपयोग किया है। एचटीएमएल) मुद्दा अभी भी जारी रहेगा। –

+0

आप एक वेबव्यू का उपयोग मध्यस्थ के रूप में कर सकते हैं जो पूरी तरह से अच्छी तरह से काम करता है। – Fuzzy

25

ACTION_INSTALL_PACKAGE के लिए दस्तावेज़ गलत है। यह भी फाइलों को स्वीकार करेगा।

इसलिए मेरा एकमात्र सुझाव अनुप्रयोग फ़ाइल क्षेत्र में फ़ाइल की प्रतिलिपि बनाना, इसे दुनिया को पठनीय बनाने और बाद की तारीख में किसी बाएं-ओवर फ़ाइलों को साफ़ करना होगा।

पिछला गलत उत्तर: // यूआरआई (JavaDoc), लेकिन यह है कि पहले आपने ACTION_VIEW के माध्यम से स्थापित करने के लिए सीमित कर रहे हैं: 4.0 और इसके बाद के संस्करण में एक ACTION_INSTALL_PACKAGE जो एक सामग्री को स्वीकार करेंगे नहीं है जो मानता है कि यूआरआई पास एक फाइल है: // यूआरआई।

+0

ओयू ... हाँ, यह नया है। बहुत धन्यवाद! – CommonsWare

+0

क्या आपने यह कोशिश की है? जब मैं 'सामग्री: //' योजना का उपयोग करता हूं, तो मुझे 'ACTION_VIEW' के समान परिणाम मिलते हैं - एक "छोड़ने वाले डीआईआर" लॉगकैट संदेश, और इंस्टॉलर बेल्स। – CommonsWare

+1

मुझे प्रलेखन में विश्वास था, लेकिन ऐसा लगता है कि दस्तावेज गलत है। कोड सर्विसिंग ACTION_INSTALL_PACKAGE केवल फाइलों को स्वीकार करेगा। एक बग रजिस्टर करने का समय। माफ़ कीजिये। –

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