package com.danikula.videocache;
import android.content.Context;
import android.net.Uri;
import com.danikula.videocache.file.DiskUsage;
import com.danikula.videocache.file.FileNameGenerator;
import com.danikula.videocache.file.Md5FileNameGenerator;
import com.danikula.videocache.file.TotalCountLruDiskUsage;
import com.danikula.videocache.file.TotalSizeLruDiskUsage;
import com.danikula.videocache.sourcestorage.SourceInfoStorage;
import com.danikula.videocache.sourcestorage.SourceInfoStorageFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static com.danikula.videocache.Preconditions.checkAllNotNull;
import static com.danikula.videocache.Preconditions.checkNotNull;
/**
* Simple lightweight proxy server with file caching support that handles HTTP requests.
* Typical usage:
* <pre><code>
* public onCreate(Bundle state) {
* super.onCreate(state);
* <p/>
* HttpProxyCacheServer proxy = getProxy();
* String proxyUrl = proxy.getProxyUrl(VIDEO_URL);
* videoView.setVideoPath(proxyUrl);
* }
* <p/>
* private HttpProxyCacheServer getProxy() {
* // should return single instance of HttpProxyCacheServer shared for whole app.
* }
* <code/></pre>
*
* @author Alexey Danilov (danikula@gmail.com).
*/
public class HttpProxyCacheServer {
private static final Logger LOG = LoggerFactory.getLogger("HttpProxyCacheServer");
private static final String PROXY_HOST = "127.0.0.1";
private final Object clientsLock = new Object();
private final ExecutorService socketProcessor = Executors.newFixedThreadPool(8);
private final Map<String, HttpProxyCacheServerClients> clientsMap = new ConcurrentHashMap<>();
private final ServerSocket serverSocket;
private final int port;
private final Thread waitConnectionThread;
private final Config config;
private final Pinger pinger;
public HttpProxyCacheServer(Context context) {
this(new Builder(context).buildConfig());
}
private HttpProxyCacheServer(Config config) {
this.config = checkNotNull(config);
try {
InetAddress inetAddress = InetAddress.getByName(PROXY_HOST);
this.serverSocket = new ServerSocket(0, 8, inetAddress);
this.port = serverSocket.getLocalPort();
CountDownLatch startSignal = new CountDownLatch(1);
this.waitConnectionThread = new Thread(new WaitRequestsRunnable(startSignal));
this.waitConnectionThread.start();
startSignal.await(); // freeze thread, wait for server starts
this.pinger = new Pinger(PROXY_HOST, port);
LOG.info("Proxy cache server started. Is it alive? " + isAlive());
} catch (IOException | InterruptedException e) {
socketProcessor.shutdown();
throw new IllegalStateException("Error starting local proxy server", e);
}
}
/**
* Returns url that wrap original url and should be used for client (MediaPlayer, ExoPlayer, etc).
* <p>
* If file for this url is fully cached (it means method {@link #isCached(String)} returns {@code true})
* then file:// uri to cached file will be returned.
* <p>
* Calling this method has same effect as calling {@link #getProxyUrl(String, boolean)} with 2nd parameter set to {@code true}.
*
* @param url a url to file that should be cached.
* @return a wrapped by proxy url if file is not fully cached or url pointed to cache file otherwise.
*/
public String getProxyUrl(String url) {
return getProxyUrl(url, true);
}
/**
* Returns url that wrap original url and should be used for client (MediaPlayer, ExoPlayer, etc).
* <p>
* If parameter {@code allowCachedFileUri} is {@code true} and file for this url is fully cached
* (it means method {@link #isCached(String)} returns {@code true}) then file:// uri to cached file will be returned.
*
* @param url a url to file that should be cached.
* @param allowCachedFileUri {@code true} if allow to return file:// uri if url is fully cached
* @return a wrapped by proxy url if file is not fully cached or url pointed to cache file otherwise (if {@code allowCachedFileUri} is {@code true}).
*/
public String getProxyUrl(String url, boolean allowCachedFileUri) {
if (allowCachedFileUri && isCached(url)) {
File cacheFile = getCacheFile(url);
touchFileSafely(cacheFile);
return Uri.fromFile(cacheFile).toString();
}
return isAlive() ? appendToProxyUrl(url) : url;
}
public void registerCacheListener(CacheListener cacheListener, String url) {
checkAllNotNull(cacheListener, url);
synchronized (clientsLock) {
try {
getClients(url).registerCacheListener(cacheListener);
} catch (ProxyCacheException e) {
LOG.warn("Error registering cache listener", e);
}
}
}
public void unregisterCacheListener(CacheListener cacheListener, String url) {
checkAllNotNull(cacheListener, url);
synchronized (clientsLock) {
try {
getClients(url).unregisterCacheListener(cacheListener);
} catch (ProxyCacheException e) {
LOG.warn("Error registering cache listener", e);
}
}
}
public void unregisterCacheListener(CacheListener cacheListener) {
checkNotNull(cacheListener);
synchronized (clientsLock) {
for (HttpProxyCacheServerClients clients : clientsMap.values()) {
clients.unregisterCacheListener(cacheListener);
}
}
}
/**
* Checks is cache contains fully cached file for particular url.
*
* @param url an url cache file will be checked for.
* @return {@code true} if cache contains fully cached file for passed in parameters url.
*/
public boolean isCached(String url) {
checkNotNull(url, "Url can't be null!");
return getCacheFile(url).exists();
}
public void shutdown() {
LOG.info("Shutdown proxy server");
shutdownClients();
config.sourceInfoStorage.release();
waitConnectionThread.interrupt();
try {
if (!serverSocket.isClosed()) {
serverSocket.close();
}
} catch (IOException e) {
onError(new ProxyCacheException("Error shutting down proxy server", e));
}
}
private boolean isAlive() {
return pinger.ping(3, 70); // 70+140+280=max~500ms
}
private String appendToProxyUrl(String url) {
return String.format(Locale.US, "http://%s:%d/%s", PROXY_HOST, port, ProxyCacheUtils.encode(url));
}
private File getCacheFile(String url) {
File cacheDir = config.cacheRoot;
String fileName = config.fileNameGenerator.generate(url);
return new File(cacheDir, fileName);
}
private void touchFileSafely(File cacheFile) {
try {
config.diskUsage.touch(cacheFile);
} catch (IOException e) {
LOG.error("Error touching file " + cacheFile, e);
}
}
private void shutdownClients() {
synchronized (clientsLock) {
for (HttpProxyCacheServerClients clients : clientsMap.values()) {
clients.shutdown();
}
clientsMap.clear();
}
}
private void waitForRequest() {
try {
while (!Thread.currentThread().isInterrupted()) {
So
没有合适的资源?快使用搜索试试~ 我知道了~
Android音频缓存(边播放变下载)
共130个文件
svn-base:66个
java:36个
xml:8个
4星 · 超过85%的资源 需积分: 48 414 下载量 78 浏览量
2016-11-30
17:31:54
上传
评论 10
收藏 233KB RAR 举报
温馨提示
所实现的功能: 1. 音频文件(我在这里使用的是mp3格式的)的播放,暂停,停止。 2. 音频文件的时长显示(还未加载完成的音频) 3. 简单的音频播放计时功能 4. 清楚缓存 5. 自动读取缓存文件(没有缓存从网络读取,有缓存的时候从本地缓存读取) 6. 进度条缓存加载提示(如果已经缓存缓存setSecondaryProgress将会设置成100%); 博客地址:http://blog.csdn.net/chezi008/article/details/53409465
资源推荐
资源详情
资源评论
收起资源包目录
Android音频缓存(边播放变下载) (130个子文件)
gradle-wrapper.properties.bak 236B
wc.db 106KB
wc.db-journal 0B
entries 3B
format 3B
.gitignore 98B
.gitignore 8B
build.gradle 961B
build.gradle 735B
build.gradle 455B
settings.gradle 37B
gradle-wrapper.jar 49KB
HttpProxyCacheServer.java 15KB
MainActivity.java 7KB
HttpUrlSource.java 7KB
ProxyCache.java 6KB
MusicService.java 5KB
FileCache.java 4KB
HttpProxyCache.java 4KB
Pinger.java 4KB
HttpProxyCacheServerClients.java 4KB
DatabaseSourceInfoStorage.java 3KB
StorageUtils.java 3KB
ProxyCacheUtils.java 3KB
Files.java 3KB
LruDiskUsage.java 2KB
GetRequest.java 2KB
ByteArrayCache.java 2KB
Source.java 1KB
Utils.java 1KB
Preconditions.java 1004B
Config.java 966B
Md5FileNameGenerator.java 943B
ByteArraySource.java 901B
TotalCountLruDiskUsage.java 681B
TotalSizeLruDiskUsage.java 666B
App.java 655B
SourceInfo.java 608B
InterruptedProxyCacheException.java 520B
SourceInfoStorageFactory.java 484B
NoSourceInfoStorage.java 474B
Cache.java 464B
ProxyCacheException.java 443B
UnlimitedDiskUsage.java 345B
SourceInfoStorage.java 329B
CacheListener.java 317B
DiskUsage.java 282B
FileNameGenerator.java 219B
ic_launcher.png 8KB
ic_launcher.png 5KB
ic_launcher.png 3KB
ic_launcher.png 2KB
proguard-rules.pro 670B
gradle.properties 872B
local.properties 459B
gradle-wrapper.properties 239B
e614e3b2edc63a9cc423437dea087c91962254f5.svn-base 49KB
d676218d9c7804e312573fbf3837d9e4f568a5cb.svn-base 15KB
41dc154e4ffff91ab2b070a4ce0ad15e50571bea.svn-base 8KB
14cba8bf18f40c7b7b47204940a7592fb9cefee3.svn-base 7KB
a4b970c5f1541f1b5bcc6abd2c49febdf1124cf8.svn-base 7KB
07b8e22d5290465296cc0ae833c07124fe437be5.svn-base 7KB
44cbd0dc0a611b1143385336f4919aa239e37d4d.svn-base 6KB
60208a9fdf2d5693eb10bc0d8c94f87b0197527a.svn-base 6KB
11a043fe72c541b96d075d398393b7cd08416768.svn-base 6KB
484e8e69a881de6a8d89e8b1dfe2d323d7853eb2.svn-base 5KB
2fbb6902ad8f919ebb2aa0b4e212eaf5d5cf06cd.svn-base 5KB
cac22ff594b3baf6d111f57405f27b485463a68c.svn-base 5KB
acdbf72b1ebd0511ac51ada3f67d1954ad71561c.svn-base 4KB
31a0c569958f6bf231edddf62016cf5cfe05f6c6.svn-base 4KB
e8f85951b44c64623a17896dd97c967347b1cc04.svn-base 4KB
266117906abd31a37eae012a9821c476cb29d316.svn-base 4KB
f5eeb9b555154e1aa2ed2c62e8fc82f4221063a3.svn-base 3KB
a78f48fe9f9114f315dc79eff29452e93ffd709a.svn-base 3KB
c44f6793b47b3831b32641ce0c01d4f97cefb615.svn-base 3KB
e769790f99809dbcf921d37ee97bcdb310d9c372.svn-base 3KB
b61e164475cad17ebe23961cde28b08be61e65a0.svn-base 3KB
09c44b5fa89c38e7f75e01169a77eb69cf9ebfa2.svn-base 3KB
6e91f14e5c588a4268379198bada7ad8475bb364.svn-base 3KB
5d5284fa47ecf9cdd21ab7618b17b65ee4593dc6.svn-base 3KB
3a1f5b9e9a81d017f3750923724fa6533e8908e6.svn-base 2KB
7d4b6be0ce5c6e30dddd77c0d742b8b4b0abe2bc.svn-base 2KB
ae86c9f2fefeb0a12f9e350975339bc580efd813.svn-base 2KB
e25e50bdeaa473f00864681f5180e702744657b8.svn-base 2KB
b13956e83a38c446e09a2c2e35a0ae7591501ae1.svn-base 1KB
8a262736d03ec43c9a64090c9df1395656ce8674.svn-base 1KB
a025510ce4b7756e32cab3bdb74a6e0a5896bb01.svn-base 1KB
6a2cc51e004b71881c06836a35212bff31a31caa.svn-base 1KB
7b29f53558eea682d926a5db31b3f534f7545bf5.svn-base 1004B
afde6f236c39bafa19df644055d846cc843fba13.svn-base 987B
fd1b0683345b73a14d7fc98191cddd9599fc4e6f.svn-base 987B
1ed88dbe9444f6ea16853f7431eb67b21aee25eb.svn-base 966B
ca902519eb6f053348cf2ca3f81530d39bdc28b0.svn-base 961B
e7fd686f518ca841364ae5adca14af6b2893679c.svn-base 943B
b8bce16a211edc57aff4c6a5c3c522080d8bfc64.svn-base 901B
e855823845ba44e6420e93e1863808382e5ff795.svn-base 735B
6cf1d37c781f9739f23b2c9bbdebccbfc807513c.svn-base 697B
2b91a4956eacfd65feaeb1902989d0018563f564.svn-base 697B
b26b404e16d62729374366a5fb07f4f14caf3b93.svn-base 681B
65ff14c53ad3a06487455ebb7139a877e38745a8.svn-base 666B
共 130 条
- 1
- 2
chezi008
- 粉丝: 24
- 资源: 13
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
- 3
前往页