2012-10-03 24 views
14

मैं पूरी तरह से लोड होने के बाद एक प्रगतिशील स्ट्रीम की गई एमपी 3 फ़ाइल को एसडी कार्ड में ले जाना चाहता हूं। क्या इसे प्राप्त करने का कोई तरीका है।मीडिया प्लेयर कैश तक पहुंच प्राप्त करना

मैंने देखा है कि प्रगतिशील स्ट्रीमिंग के दौरान MediaPlayer पूरी फ़ाइल पूरी तरह से डाउनलोड करता है और फिर हम फ़ाइल के किसी भी हिस्से को खोज सकते हैं। मैं पूरी तरह से स्ट्रीम की गई फाइल को बाहरी स्टोरेज में ले जाना चाहता हूं ताकि भविष्य में प्लेबैक डेटा और बैटरी को बर्बाद न करे।

+2

उसका सबसे अच्छा जवाब ई, अगर कोई अभी भी समाधान की तलाश में है: http://stackoverflow.com/a/12044709/1548464 – Taras

उत्तर

10

मूल पोस्ट सही दिशा में अंक पर टिप्पणी है, लेकिन मैंने सोचा कि यह एक सा व्याख्या करने के लिए सहायक हो सकता है ...

मैंने क्या किया गया है नागा और का उपयोग कर एक हल्के प्रॉक्सी सर्वर का निर्माण होता है अपाचे HTTP पुस्तकालय। इस भाग की मूल बातें पाने के लिए वहां बहुत से उदाहरण हो सकते हैं। MediaPlayer को एक उपयुक्त लोकलहोस्ट यूआरएल प्रदान करें ताकि यह आपके प्रॉक्सी में सॉकेट खोल सके। जब मीडियाप्लेयर अनुरोध करता है, तो वास्तविक मीडिया होस्ट को समकक्ष अनुरोध भेजने के लिए प्रॉक्सी का उपयोग करें। आपको प्रॉक्सी के पैकेट रीसेट विधि में बाइट [] डेटा प्राप्त होगा, जिसे मैं एक HttpGet बनाने के लिए उपयोग करता हूं और इसे AndroidHttpClient के साथ अपने रास्ते पर भेजता हूं।

आप एक HttpResponse वापस प्राप्त करेंगे और आप स्ट्रीमिंग बाइट डेटा तक पहुंचने के लिए अंदर HttpEntity का उपयोग कर सकते हैं। मैं एक ReadableByteChannel उपयोग कर रहा हूँ, इसलिए जैसे:

HttpEntityWrapper entity = (HttpEntityWrapper)response.getEntity(); 
ReadableByteChannel src = Channels.newChannel(entity.getContent()); 

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

int read, written; 
SocketChannel dst = client.getChannel(); 
while (dst.isConnected() && 
    dst.isOpen() && 
    src.isOpen() && 
    (read = src.read(buffer)) >= 0) { 
    try { 
     buffer.flip(); 
     // This is one point where you can access the stream data. 
     // Just remember to reset the buffer position before trying 
     // to write to the destination. 
     if (buffer.hasRemaining()) { 
      written = dst.write(buffer); 
      // If the player isn't reading, wait a bit. 
      if (written == 0) Thread.sleep(15); 
      buffer.compact(); 
     } 
    } 
    catch (IOException ex) { 
     // handle error 
    } 
} 

आप खिलाड़ी के साथ इसे पारित करने से पहले जवाब में मेजबान हैडर को बदलने के लिए आवश्यकता हो सकती है तो ऐसा लगता है कि आपके प्रॉक्सी की तरह इस है, लेकिन मैं MediaPlayer के स्वामित्व कार्यान्वयन इसलिए व्यवहार के साथ काम कर रहा है कि थोड़ा अलग हो सकता है। उम्मीद है की वो मदद करदे।

+2

क्या आप प्रॉक्सी बनाने और डेटा को अवरुद्ध करने के तरीके पर कुछ और कोड साझा कर सकते हैं ?? – anz

+0

हम मध्यस्थ अनुरोध को कैसे रोक सकते हैं? – anz

14

विचार यह है कि वेब प्लेयर सीधे डेटा पढ़ने के बजाय मीडिया प्लेयर पढ़ सकता है।

मैंने danikula/AndroidVideoCache का उपयोग किया जो कि निर्माण/उपयोग करने के लिए बहुत आसान है। मैंने ऑडियो के लिए वीडियो का उपयोग नहीं किया, लेकिन यह वही है।

+1

यह सही जवाब होना चाहिए। प्रत्यक्ष और उपयोग करने में आसान। काश मैं 10 वोट दे सकता हूं। – MetaSnarf

+0

मैं कैश फ़ाइल कैसे एन्क्रिप्ट कर सकता हूं? –

3

देर से लेकिन मुझे पता चला कि ज्यादातर लोगों को अभी भी समाधान की आवश्यकता है। मेरा समाधान JakeWharton's DiskLruCache पर आधारित है।

: हम कैश

चरण 1 से InputStram/FileDescriptor के लिए दो बातें

  • AsyncTask फ़ाइल को पढ़ने या नेटवर्क से डाउनलोड करने और कैश यह

  • कॉलबैक करने की जरूरत है

    import android.content.Context; 
    import android.os.AsyncTask; 
    import org.apache.commons.io.IOUtils; 
    import java.io.FileInputStream; 
    import java.io.IOException; 
    import java.io.InputStream; 
    import java.io.OutputStream; 
    import java.net.HttpURLConnection; 
    import java.net.URL; 
    
    // you can use FileDescriptor as 
    // extends AsyncTask<String, Void, FileDescriptor> 
    
    public class AudioStreamWorkerTask extends AsyncTask<String, Void, FileInputStream> { 
    
        private OnCacheCallback callback = null; 
        private Context context = null; 
    
        public AudioStreamWorkerTask(Context context, OnCacheCallback callback) { 
         this.context = context; 
         this.callback = callback; 
        } 
    
        @Override 
        protected FileInputStream doInBackground(String... params) { 
         String data = params[0]; 
         // Application class where i did open DiskLruCache 
         DiskLruCache cache = MyApplication.getDiskCache(context); 
         if (cache == null) 
          return null; 
         String key = hashKeyForDisk(data); 
         final int DISK_CACHE_INDEX = 0; 
         long currentMaxSize = cache.getMaxSize(); 
         float percentageSize = Math.round((cache.size() * 100.0f)/currentMaxSize); 
         if (percentageSize >= 90) // cache size reaches 90% 
          cache.setMaxSize(currentMaxSize + (10 * 1024 * 1024)); // increase size to 10MB 
         try { 
          DiskLruCache.Snapshot snapshot = cache.get(key); 
          if (snapshot == null) { 
           Log.i(getTag(), "Snapshot is not available downloading..."); 
           DiskLruCache.Editor editor = cache.edit(key); 
           if (editor != null) { 
            if (downloadUrlToStream(data, editor.newOutputStream(DISK_CACHE_INDEX))) 
             editor.commit(); 
            else 
             editor.abort(); 
           } 
           snapshot = cache.get(key); 
          } else 
           Log.i(getTag(), "Snapshot found sending"); 
          if (snapshot != null) 
           return (FileInputStream) snapshot.getInputStream(DISK_CACHE_INDEX); 
         } catch (IOException e) { 
          e.printStackTrace(); 
         } 
         Log.i(getTag(), "File stream is null"); 
         return null; 
        } 
    
        @Override 
        protected void onPostExecute(FileInputStream fileInputStream) { 
         super.onPostExecute(fileInputStream); 
         if (callback != null) { 
          if (fileInputStream != null) 
           callback.onSuccess(fileInputStream); 
          else 
           callback.onError(); 
         } 
         callback = null; 
         context = null; 
        } 
    
        public boolean downloadUrlToStream(String urlString, OutputStream outputStream) { 
         HttpURLConnection urlConnection = null; 
         try { 
          final URL url = new URL(urlString); 
          urlConnection = (HttpURLConnection) url.openConnection(); 
          InputStream stream = urlConnection.getInputStream(); 
          // you can use BufferedInputStream and BufferOuInputStream 
          IOUtils.copy(stream, outputStream); 
          IOUtils.closeQuietly(outputStream); 
          IOUtils.closeQuietly(stream); 
          Log.i(getTag(), "Stream closed all done"); 
          return true; 
         } catch (final IOException e) { 
          e.printStackTrace(); 
         } finally { 
          if (urlConnection != null) 
           IOUtils.close(urlConnection); 
         } 
         return false; 
        } 
    
        private String getTag() { 
         return getClass().getSimpleName(); 
        } 
    
        private String hashKeyForDisk(String key) { 
         String cacheKey; 
         try { 
          final MessageDigest mDigest = MessageDigest.getInstance("MD5"); 
          mDigest.update(key.getBytes()); 
          cacheKey = bytesToHexString(mDigest.digest()); 
         } catch (NoSuchAlgorithmException e) { 
          cacheKey = String.valueOf(key.hashCode()); 
         } 
         return cacheKey; 
        } 
    
        private String bytesToHexString(byte[] bytes) { 
         // http://stackoverflow.com/questions/332079 
         StringBuilder sb = new StringBuilder(); 
         for (byte aByte : bytes) { 
          String hex = Integer.toHexString(0xFF & aByte); 
          if (hex.length() == 1) 
           sb.append('0'); 
          sb.append(hex); 
         } 
         return sb.toString(); 
        } 
    } 
    

    चरण 2:

    public interface OnCacheCallback { 
    
        void onSuccess(FileInputStream stream); 
    
        void onError(); 
    } 
    

    उदाहरण

    final String path = "http://www.example.com/test.mp3"; 
    new AudioStreamWorkerTask (TestActivity.this, new OnCacheCallback() { 
    
    @Override 
    public void onSuccess(FileInputStream fileInputStream) { 
        Log.i(getClass().getSimpleName() + ".MediaPlayer", "now playing..."); 
        if (fileInputStream != null) { 
         // reset media player here if necessary 
         mediaPlayer = new MediaPlayer(); 
         try { 
          mediaPlayer.setDataSource(fileInputStream.getFD()); 
          mediaPlayer.prepare(); 
          mediaPlayer.setVolume(1f, 1f); 
          mediaPlayer.setLooping(false); 
          mediaPlayer.start(); 
          fileInputStream.close(); 
         } catch (IOException | IllegalStateException e) { 
          e.printStackTrace(); 
         } 
        } else { 
         Log.e(getClass().getSimpleName() + ".MediaPlayer", "fileDescriptor is not valid"); 
        } 
    } 
    
    @Override 
    public void onError() { 
        Log.e(getClass().getSimpleName() + ".MediaPlayer", "Can't play audio file"); 
    } 
    }).execute(path); 
    

    नोट:

    यह परीक्षण किया जाता है लेकिन ऑडियो फ़ाइल कैशिंग के लिए किसी न किसी तरह नमूना, वहाँ कुछ भी हो सकती हैं यदि आप पाते हैं कृपया मुझे सूचित करें :)

+0

इस '// एप्लिकेशन क्लास के द्वारा आपका क्या मतलब है, जहां मैंने डिस्कक्लुशैच' – Naz141

+0

खोला था, अपने एप्लिकेशन क्लास (एप्लिकेशन के साथ विस्तारित) में डिस्कलक्रैच शुरू करें, या जहां भी आप चाहें :) –

+0

यदि आप मुझे कोड का टुकड़ा दिखा सकते हैं DiskLruCache की शुरुआत लिखी। धन्यवाद – Naz141

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