├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── README.md
├── app
├── .gitignore
├── build.gradle
├── libs
│ └── android-support-v4.jar
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── github
│ │ └── mediaserver
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── mediaserver
│ │ │ ├── DeviceInfo.java
│ │ │ ├── DeviceUpdateBrocastFactory.java
│ │ │ ├── DeviceUpdateBrocastReceiver.java
│ │ │ ├── MainActivity.java
│ │ │ ├── ServerApplication.java
│ │ │ ├── server
│ │ │ ├── DMSService.java
│ │ │ ├── center
│ │ │ │ ├── DMSWorkThread.java
│ │ │ │ ├── IBaseEngine.java
│ │ │ │ ├── LocalConfigSharePreference.java
│ │ │ │ ├── MediaServerProxy.java
│ │ │ │ └── MediaStoreCenter.java
│ │ │ ├── jni
│ │ │ │ └── DMSJniInterface.java
│ │ │ └── media
│ │ │ │ ├── IMediaScanListener.java
│ │ │ │ └── MediaScannerCenter.java
│ │ │ └── util
│ │ │ ├── CommonLog.java
│ │ │ ├── CommonUtil.java
│ │ │ ├── DlnaUtils.java
│ │ │ ├── FileHelper.java
│ │ │ └── LogFactory.java
│ ├── jniLibs
│ │ └── armeabi
│ │ │ └── libgit-platinum.so
│ └── res
│ │ ├── drawable-hdpi
│ │ ├── ic_launcher.png
│ │ └── main_bg.png
│ │ ├── drawable-ldpi
│ │ └── ic_launcher.png
│ │ ├── drawable-mdpi
│ │ └── ic_launcher.png
│ │ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ │ ├── drawable
│ │ ├── button_normal.9.png
│ │ ├── button_pressed.9.png
│ │ ├── input_disabled.9.png
│ │ ├── input_normal.9.png
│ │ ├── input_pressed.9.png
│ │ ├── logo.png
│ │ ├── selector_btn.xml
│ │ └── selector_edit.xml
│ │ ├── layout
│ │ └── activity_main.xml
│ │ └── values
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── github
│ └── mediaserver
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | MediaServer
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | a MediaServer run in Android Platform
2 | ===========
3 | MediaServer is a DLNA device(DMS) that can be browsed by control
It uses the framework of Platinum
4 |
5 | Example screenshot below:
6 |
7 | 
8 |
9 |
10 |
11 | Code fragment
12 | --------------------
13 | public class DMSService extends Service implements IBaseEngine{
14 |
15 | private static final CommonLog log = LogFactory.createLog();
16 |
17 | public static final String START_SERVER_ENGINE = "com.geniusgithub.start.dmsengine";
18 | public static final String RESTART_SERVER_ENGINE = "com.geniusgithub.restart.dmsengine";
19 |
20 | private DMSWorkThread mWorkThread;
21 |
22 | private Handler mHandler;
23 | private static final int START_ENGINE_MSG_ID = 0x0001;
24 | private static final int RESTART_ENGINE_MSG_ID = 0x0002;
25 |
26 | private static final int DELAY_TIME = 1000;
27 |
28 | private MediaStoreCenter mMediaStoreCenter;
29 |
30 | @Override
31 | public IBinder onBind(Intent intent) {
32 | return null;
33 | }
34 |
35 | @Override
36 | public void onCreate() {
37 | super.onCreate();
38 | initService();
39 | log.e("MediaServerService onCreate");
40 | }
41 |
42 | @Override
43 | public void onDestroy() {
44 | unInitService();
45 | log.e("MediaServerService onDestroy");
46 | super.onDestroy();
47 |
48 | }
49 |
50 | @Override
51 | public int onStartCommand(Intent intent, int flags, int startId) {
52 |
53 | if (intent != null){
54 | String actionString = intent.getAction();
55 | if (actionString != null){
56 | if (actionString.equalsIgnoreCase(START_SERVER_ENGINE)){
57 | delayToSendStartMsg();
58 | }else if (actionString.equalsIgnoreCase(RESTART_SERVER_ENGINE)){
59 | delayToSendRestartMsg();
60 | }
61 | }
62 | }
63 |
64 | return super.onStartCommand(intent, flags, startId);
65 |
66 | }
67 |
68 |
69 | private void initService(){
70 |
71 | mWorkThread = new DMSWorkThread(this);
72 |
73 | mHandler = new Handler(){
74 | @Override
75 | public void handleMessage(Message msg) {
76 | switch(msg.what){
77 | case START_ENGINE_MSG_ID:
78 | startEngine();
79 | break;
80 | case RESTART_ENGINE_MSG_ID:
81 | restartEngine();
82 | break;
83 | }
84 | }
85 |
86 | };
87 |
88 | mMediaStoreCenter = MediaStoreCenter.getInstance();
89 | mMediaStoreCenter.clearWebFolder();
90 | mMediaStoreCenter.createWebFolder();
91 | mMediaStoreCenter.doScanMedia();
92 | }
93 |
94 |
95 | private void unInitService(){
96 | stopEngine();
97 | removeStartMsg();
98 | removeRestartMsg();
99 | mMediaStoreCenter.clearAllData();
100 | }
101 |
102 | private void delayToSendStartMsg(){
103 | removeStartMsg();
104 | mHandler.sendEmptyMessageDelayed(START_ENGINE_MSG_ID, DELAY_TIME);
105 | }
106 |
107 | private void delayToSendRestartMsg(){
108 | removeStartMsg();
109 | removeRestartMsg();
110 | mHandler.sendEmptyMessageDelayed(RESTART_ENGINE_MSG_ID, DELAY_TIME);
111 | }
112 |
113 | private void removeStartMsg(){
114 | mHandler.removeMessages(START_ENGINE_MSG_ID);
115 | }
116 |
117 | private void removeRestartMsg(){
118 | mHandler.removeMessages(RESTART_ENGINE_MSG_ID);
119 | }
120 |
121 |
122 | @Override
123 | public boolean startEngine() {
124 | awakeWorkThread();
125 | return true;
126 | }
127 |
128 | @Override
129 | public boolean stopEngine() {
130 | mWorkThread.setParam("", "", "");
131 | exitWorkThread();
132 | return true;
133 | }
134 |
135 | @Override
136 | public boolean restartEngine() {
137 | String friendName = DlnaUtils.getDevName(this);
138 | String uuid = DlnaUtils.creat12BitUUID(this);
139 | mWorkThread.setParam(mMediaStoreCenter.getRootDir(), friendName, uuid);
140 | if (mWorkThread.isAlive()){
141 | mWorkThread.restartEngine();
142 | }else{
143 | mWorkThread.start();
144 | }
145 | return true;
146 | }
147 |
148 | private void awakeWorkThread(){
149 | String friendName = DlnaUtils.getDevName(this);
150 | String uuid = DlnaUtils.creat12BitUUID(this);
151 | mWorkThread.setParam(mMediaStoreCenter.getRootDir(), friendName, uuid);
152 |
153 |
154 | if (mWorkThread.isAlive()){
155 | mWorkThread.awakeThread();
156 | }else{
157 | mWorkThread.start();
158 | }
159 | }
160 |
161 | private void exitWorkThread(){
162 | if (mWorkThread != null && mWorkThread.isAlive()){
163 | mWorkThread.exit();
164 | long time1 = System.currentTimeMillis();
165 | while(mWorkThread.isAlive()){
166 | try {
167 | Thread.sleep(100);
168 | } catch (InterruptedException e) {
169 | e.printStackTrace();
170 | }
171 | }
172 | long time2 = System.currentTimeMillis();
173 | log.e("exitWorkThread cost time:" + (time2 - time1));
174 | mWorkThread = null;
175 | }
176 | }
177 |
178 |
179 | }
180 |
181 |
182 |
183 | public class DMSWorkThread extends Thread implements IBaseEngine{
184 |
185 |
186 | private static final CommonLog log = LogFactory.createLog();
187 |
188 | private static final int CHECK_INTERVAL = 30 * 1000;
189 |
190 | private Context mContext = null;
191 | private boolean mStartSuccess = false;
192 | private boolean mExitFlag = false;
193 |
194 | private String mRootdir = "";
195 | private String mFriendName = "";
196 | private String mUUID = "";
197 | private ServerApplication mApplication;
198 |
199 | public DMSWorkThread(Context context){
200 | mContext = context;
201 | mApplication = ServerApplication.getInstance();
202 | }
203 |
204 | public void setFlag(boolean flag){
205 | mStartSuccess = flag;
206 | }
207 |
208 | public void setParam(String rootDir, String friendName, String uuid){
209 | mRootdir = rootDir;
210 | mFriendName = friendName;
211 | mUUID = uuid;
212 | mApplication.updateDevInfo(mRootdir, mFriendName, mUUID);
213 | }
214 |
215 | public void awakeThread(){
216 | synchronized (this) {
217 | notifyAll();
218 | }
219 | }
220 |
221 | public void exit(){
222 | mExitFlag = true;
223 | awakeThread();
224 | }
225 |
226 | @Override
227 | public void run() {
228 |
229 | log.e("DMSWorkThread run...");
230 |
231 | while(true)
232 | {
233 | if (mExitFlag){
234 | stopEngine();
235 | break;
236 | }
237 | refreshNotify();
238 | synchronized(this)
239 | {
240 | try
241 | {
242 | wait(CHECK_INTERVAL);
243 | }
244 | catch(Exception e)
245 | {
246 | e.printStackTrace();
247 | }
248 | }
249 | if (mExitFlag){
250 | stopEngine();
251 | break;
252 | }
253 | }
254 |
255 | log.e("DMSWorkThread over...");
256 |
257 | }
258 |
259 | public void refreshNotify(){
260 | if (!CommonUtil.checkNetworkState(mContext)){
261 | return ;
262 | }
263 |
264 | if (!mStartSuccess){
265 | stopEngine();
266 | try {
267 | Thread.sleep(200);
268 | } catch (InterruptedException e) {
269 | e.printStackTrace();
270 | }
271 | boolean ret = startEngine();
272 | if (ret){
273 | mStartSuccess = true;
274 | }
275 | }
276 |
277 | }
278 |
279 | @Override
280 | public boolean startEngine() {
281 | if (mFriendName.length() == 0){
282 | return false;
283 | }
284 |
285 | int ret = DMSJniInterface.startServer(mRootdir, mFriendName, mUUID);
286 |
287 | boolean result = (ret == 0 ? true : false);
288 | mApplication.setDevStatus(result);
289 | return result;
290 | }
291 |
292 | @Override
293 | public boolean stopEngine() {
294 | DMSJniInterface.stopServer();
295 | mApplication.setDevStatus(false);
296 | return true;
297 | }
298 |
299 | @Override
300 | public boolean restartEngine() {
301 | setFlag(false);
302 | awakeThread();
303 | return true;
304 | }
305 |
306 | }
307 |
308 |
309 |
310 | Run requirements
311 | ------------------------------
312 | Android OS 2.3x and up
313 | Tested with: Samsung, HTC, HuaWei Phone and so on...
314 |
315 |
316 | Contributing
317 | ------------------------------
318 | Feel free to drop me pull requests. If you plan to implement something more than a few lines, then open the pull request early so that there aren't any nasty surprises later.
319 | If you want to add something that will require some for of persistence incl. persistent configuration or API keys, etc., then open a pull request/issue especially early!
320 |
321 |
322 | ### Links
323 | csdn blog : [http://blog.csdn.net/geniuseoe2012](http://blog.csdn.net/geniuseoe2012)
324 | cnblog : [http://www.cnblogs.com/lance2016](http://www.cnblogs.com/lance2016/p/5204315.html)
325 | dlna doc: [DLNA Document](http://download.csdn.net/detail/geniuseoe2012/4969961)
326 | Platinum SDK : [Platinum](http://sourceforge.net/projects/platinum/)
327 |
328 | ### Development
329 | If you think this article useful Nepal , please pay attention to me
330 | Your support is my motivation, I will continue to strive to do better
331 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 22
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | applicationId "com.github.mediaserver"
9 | minSdkVersion 19
10 | targetSdkVersion 22
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | testCompile 'junit:junit:4.12'
25 | }
26 |
--------------------------------------------------------------------------------
/app/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in E:\sofeware\android-sdk-L/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/github/mediaserver/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.github.mediaserver;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/mediaserver/DeviceInfo.java:
--------------------------------------------------------------------------------
1 | package com.github.mediaserver;
2 |
3 | public class DeviceInfo {
4 |
5 | public String dev_name;
6 | public String uuid;
7 | public String rootDir;
8 | public boolean status;
9 |
10 | public DeviceInfo(){
11 | rootDir = "";
12 | dev_name = "";
13 | uuid = "";
14 | status = false;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/mediaserver/DeviceUpdateBrocastFactory.java:
--------------------------------------------------------------------------------
1 | package com.github.mediaserver;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.content.IntentFilter;
6 |
7 |
8 | public class DeviceUpdateBrocastFactory {
9 |
10 | public static final String PARAM_DEV_UPDATE="com.geniusgithub.dms.PARAM_DEV_UPDATE";
11 |
12 | public static interface IDevUpdateListener {
13 | public void onUpdate();
14 | }
15 |
16 |
17 | private DeviceUpdateBrocastReceiver mReceiver;
18 | private Context mContext;
19 |
20 | public DeviceUpdateBrocastFactory(Context context){
21 | mContext = context;
22 | }
23 |
24 |
25 | public void register(IDevUpdateListener listener){
26 | if (mReceiver == null){
27 | mReceiver = new DeviceUpdateBrocastReceiver();
28 | mReceiver.setListener(listener);
29 | mContext.registerReceiver(mReceiver, new IntentFilter(PARAM_DEV_UPDATE));
30 | }
31 | }
32 |
33 | public void unregister()
34 | {
35 | if (mReceiver != null){
36 | mContext.unregisterReceiver(mReceiver);
37 | mReceiver = null;
38 | }
39 | }
40 |
41 | public static void sendDevUpdateBrocast(Context context){
42 | Intent intent = new Intent();
43 | intent.setAction(PARAM_DEV_UPDATE);
44 | context.sendBroadcast(intent);
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/mediaserver/DeviceUpdateBrocastReceiver.java:
--------------------------------------------------------------------------------
1 | package com.github.mediaserver;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 |
7 | import com.github.mediaserver.util.CommonLog;
8 | import com.github.mediaserver.util.LogFactory;
9 |
10 |
11 |
12 | public class DeviceUpdateBrocastReceiver extends BroadcastReceiver{
13 |
14 | private static final CommonLog log = LogFactory.createLog();
15 | private DeviceUpdateBrocastFactory.IDevUpdateListener mListener;
16 |
17 | public void setListener(DeviceUpdateBrocastFactory.IDevUpdateListener listener){
18 | mListener = listener;
19 | }
20 | @Override
21 | public void onReceive(Context context, Intent intent) {
22 | String action = intent.getAction();
23 | if (action == null){
24 | return ;
25 | }
26 |
27 | if (DeviceUpdateBrocastFactory.PARAM_DEV_UPDATE.equalsIgnoreCase(action)){
28 | if (mListener != null){
29 | mListener.onUpdate();
30 | }
31 | }
32 | }
33 |
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/mediaserver/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.github.mediaserver;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.view.View.OnClickListener;
7 | import android.widget.Button;
8 | import android.widget.EditText;
9 | import android.widget.TextView;
10 |
11 | import com.github.mediaserver.server.center.MediaServerProxy;
12 | import com.github.mediaserver.util.CommonLog;
13 | import com.github.mediaserver.util.DlnaUtils;
14 | import com.github.mediaserver.util.LogFactory;
15 |
16 |
17 | /**
18 | * @author lance
19 | * @csdn http://blog.csdn.net/geniuseoe2012
20 | * @github https://github.com/geniusgithub
21 | */
22 | public class MainActivity extends Activity implements OnClickListener, DeviceUpdateBrocastFactory.IDevUpdateListener{
23 |
24 | private static final CommonLog log = LogFactory.createLog();
25 |
26 | private Button mBtnStart;
27 | private Button mBtnReset;
28 | private Button mBtnStop;
29 |
30 | private Button mBtnEditName;
31 | private EditText mETName;
32 | private TextView mTVDevInfo;
33 |
34 |
35 | private MediaServerProxy mServerProxy;
36 | private ServerApplication mApplication;
37 | private DeviceUpdateBrocastFactory mBrocastFactory;
38 |
39 | @Override
40 | protected void onCreate(Bundle savedInstanceState) {
41 | super.onCreate(savedInstanceState);
42 | setContentView(R.layout.activity_main);
43 |
44 | setupView();
45 | initData();
46 | }
47 |
48 |
49 |
50 |
51 | @Override
52 | protected void onDestroy() {
53 | unInitData();
54 | super.onDestroy();
55 | }
56 |
57 |
58 |
59 |
60 | private void setupView(){
61 | mBtnStart = (Button) findViewById(R.id.btn_init);
62 | mBtnReset = (Button) findViewById(R.id.btn_reset);
63 | mBtnStop = (Button) findViewById(R.id.btn_exit);
64 | mBtnEditName = (Button) findViewById(R.id.bt_dev_name);
65 | mBtnStart.setOnClickListener(this);
66 | mBtnReset.setOnClickListener(this);
67 | mBtnStop.setOnClickListener(this);
68 | mBtnEditName.setOnClickListener(this);
69 |
70 | mTVDevInfo = (TextView) findViewById(R.id.tv_dev_info);
71 | mETName = (EditText) findViewById(R.id.et_dev_name);
72 |
73 | }
74 |
75 | private void initData(){
76 | mApplication = ServerApplication.getInstance();
77 | mServerProxy = MediaServerProxy.getInstance();
78 | mBrocastFactory = new DeviceUpdateBrocastFactory(this);
79 |
80 | String dev_name = DlnaUtils.getDevName(this);
81 | mETName.setText(dev_name);
82 | mETName.setEnabled(false);
83 |
84 | updateDevInfo(mApplication.getDevInfo());
85 | mBrocastFactory.register(this);
86 | }
87 |
88 | private void unInitData(){
89 | mBrocastFactory.unregister();
90 | }
91 |
92 | private void updateDevInfo(DeviceInfo object){
93 | String status = object.status ? "open" : "close";
94 | String text = "status: " + status + "\n" +
95 | "friend name: " + object.dev_name + "\n" +
96 | "uuid: " + object.uuid;
97 | mTVDevInfo.setText(text);
98 | }
99 |
100 | @Override
101 | public void onClick(View v) {
102 | switch(v.getId()){
103 | case R.id.btn_init:
104 | start();
105 | break;
106 | case R.id.btn_reset:
107 | reset();
108 | break;
109 | case R.id.btn_exit:
110 | stop();
111 | finish();
112 | break;
113 | case R.id.bt_dev_name:
114 | change();
115 | break;
116 | }
117 | }
118 |
119 |
120 | private void start(){
121 | mServerProxy.startEngine();
122 | }
123 |
124 | private void reset(){
125 | mServerProxy.restartEngine();
126 | }
127 |
128 | private void stop(){
129 | mServerProxy.stopEngine();
130 | }
131 |
132 | private void change(){
133 | if (mETName.isEnabled()){
134 | mETName.setEnabled(false);
135 | DlnaUtils.setDevName(this, mETName.getText().toString());
136 | }else{
137 | mETName.setEnabled(true);
138 | }
139 | }
140 |
141 |
142 |
143 | @Override
144 | public void onUpdate() {
145 | updateDevInfo(mApplication.getDevInfo());
146 | }
147 |
148 | }
149 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/mediaserver/ServerApplication.java:
--------------------------------------------------------------------------------
1 | package com.github.mediaserver;
2 |
3 | import com.github.mediaserver.util.CommonLog;
4 | import com.github.mediaserver.util.LogFactory;
5 |
6 | import android.app.Application;
7 |
8 |
9 |
10 | public class ServerApplication extends Application{
11 |
12 | private static final CommonLog log = LogFactory.createLog();
13 |
14 | private static ServerApplication mInstance;
15 |
16 | private DeviceInfo mDeviceInfo;
17 |
18 |
19 | public synchronized static ServerApplication getInstance(){
20 | return mInstance;
21 | }
22 | @Override
23 | public void onCreate() {
24 | super.onCreate();
25 | log.e("ServerApplication onCreate");
26 |
27 | mInstance = this;
28 | mDeviceInfo = new DeviceInfo();
29 | }
30 |
31 | public void updateDevInfo(String rootDir, String name, String uuid){
32 | mDeviceInfo.rootDir = rootDir;
33 | mDeviceInfo.dev_name = name;
34 | mDeviceInfo.uuid = uuid;
35 | }
36 |
37 | public void setDevStatus(boolean flag){
38 | mDeviceInfo.status = flag;
39 | DeviceUpdateBrocastFactory.sendDevUpdateBrocast(this);
40 | }
41 |
42 | public DeviceInfo getDevInfo(){
43 | return mDeviceInfo;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/mediaserver/server/DMSService.java:
--------------------------------------------------------------------------------
1 | package com.github.mediaserver.server;
2 |
3 |
4 |
5 |
6 | import android.app.Service;
7 | import android.content.Intent;
8 | import android.net.wifi.WifiManager.MulticastLock;
9 | import android.os.Handler;
10 | import android.os.IBinder;
11 | import android.os.Message;
12 |
13 | import com.github.mediaserver.server.center.DMSWorkThread;
14 | import com.github.mediaserver.server.center.IBaseEngine;
15 | import com.github.mediaserver.server.center.MediaStoreCenter;
16 | import com.github.mediaserver.util.CommonLog;
17 | import com.github.mediaserver.util.CommonUtil;
18 | import com.github.mediaserver.util.DlnaUtils;
19 | import com.github.mediaserver.util.LogFactory;
20 |
21 | public class DMSService extends Service implements IBaseEngine{
22 |
23 | private static final CommonLog log = LogFactory.createLog();
24 |
25 | public static final String START_SERVER_ENGINE = "com.geniusgithub.start.dmsengine";
26 | public static final String RESTART_SERVER_ENGINE = "com.geniusgithub.restart.dmsengine";
27 |
28 | private DMSWorkThread mWorkThread;
29 |
30 | private Handler mHandler;
31 | private static final int START_ENGINE_MSG_ID = 0x0001;
32 | private static final int RESTART_ENGINE_MSG_ID = 0x0002;
33 |
34 | private static final int DELAY_TIME = 1000;
35 |
36 | private MediaStoreCenter mMediaStoreCenter;
37 | private MulticastLock mMulticastLock;
38 | @Override
39 | public IBinder onBind(Intent intent) {
40 | return null;
41 | }
42 |
43 | @Override
44 | public void onCreate() {
45 | super.onCreate();
46 | initService();
47 | log.e("MediaServerService onCreate");
48 | }
49 |
50 | @Override
51 | public void onDestroy() {
52 | unInitService();
53 | log.e("MediaServerService onDestroy");
54 | super.onDestroy();
55 |
56 | }
57 |
58 | @Override
59 | public int onStartCommand(Intent intent, int flags, int startId) {
60 |
61 | if (intent != null){
62 | String actionString = intent.getAction();
63 | if (actionString != null){
64 | if (actionString.equalsIgnoreCase(START_SERVER_ENGINE)){
65 | delayToSendStartMsg();
66 | }else if (actionString.equalsIgnoreCase(RESTART_SERVER_ENGINE)){
67 | delayToSendRestartMsg();
68 | }
69 | }
70 | }
71 |
72 | return super.onStartCommand(intent, flags, startId);
73 |
74 | }
75 |
76 |
77 | private void initService(){
78 |
79 | mWorkThread = new DMSWorkThread(this);
80 |
81 | mHandler = new Handler(){
82 | @Override
83 | public void handleMessage(Message msg) {
84 | switch(msg.what){
85 | case START_ENGINE_MSG_ID:
86 | startEngine();
87 | break;
88 | case RESTART_ENGINE_MSG_ID:
89 | restartEngine();
90 | break;
91 | }
92 | }
93 |
94 | };
95 |
96 | mMediaStoreCenter = MediaStoreCenter.getInstance();
97 | mMediaStoreCenter.clearWebFolder();
98 | mMediaStoreCenter.createWebFolder();
99 | mMediaStoreCenter.doScanMedia();
100 |
101 | mMulticastLock = CommonUtil.openWifiBrocast(this);
102 | log.e("openWifiBrocast = " + mMulticastLock != null ? true : false);
103 | }
104 |
105 |
106 | private void unInitService(){
107 | stopEngine();
108 | removeStartMsg();
109 | removeRestartMsg();
110 | mMediaStoreCenter.clearAllData();
111 |
112 | if (mMulticastLock != null){
113 | mMulticastLock.release();
114 | mMulticastLock = null;
115 | log.e("closeWifiBrocast");
116 | }
117 | }
118 |
119 | private void delayToSendStartMsg(){
120 | removeStartMsg();
121 | mHandler.sendEmptyMessageDelayed(START_ENGINE_MSG_ID, DELAY_TIME);
122 | }
123 |
124 | private void delayToSendRestartMsg(){
125 | removeStartMsg();
126 | removeRestartMsg();
127 | mHandler.sendEmptyMessageDelayed(RESTART_ENGINE_MSG_ID, DELAY_TIME);
128 | }
129 |
130 | private void removeStartMsg(){
131 | mHandler.removeMessages(START_ENGINE_MSG_ID);
132 | }
133 |
134 | private void removeRestartMsg(){
135 | mHandler.removeMessages(RESTART_ENGINE_MSG_ID);
136 | }
137 |
138 |
139 | @Override
140 | public boolean startEngine() {
141 | awakeWorkThread();
142 | return true;
143 | }
144 |
145 | @Override
146 | public boolean stopEngine() {
147 | mWorkThread.setParam("", "", "");
148 | exitWorkThread();
149 | return true;
150 | }
151 |
152 | @Override
153 | public boolean restartEngine() {
154 | String friendName = DlnaUtils.getDevName(this);
155 | String uuid = DlnaUtils.creat12BitUUID(this);
156 | mWorkThread.setParam(mMediaStoreCenter.getRootDir(), friendName, uuid);
157 | if (mWorkThread.isAlive()){
158 | mWorkThread.restartEngine();
159 | }else{
160 | mWorkThread.start();
161 | }
162 | return true;
163 | }
164 |
165 | private void awakeWorkThread(){
166 | String friendName = DlnaUtils.getDevName(this);
167 | String uuid = DlnaUtils.creat12BitUUID(this);
168 | mWorkThread.setParam(mMediaStoreCenter.getRootDir(), friendName, uuid);
169 |
170 |
171 | if (mWorkThread.isAlive()){
172 | mWorkThread.awakeThread();
173 | }else{
174 | mWorkThread.start();
175 | }
176 | }
177 |
178 | private void exitWorkThread(){
179 | if (mWorkThread != null && mWorkThread.isAlive()){
180 | mWorkThread.exit();
181 | long time1 = System.currentTimeMillis();
182 | while(mWorkThread.isAlive()){
183 | try {
184 | Thread.sleep(100);
185 | } catch (InterruptedException e) {
186 | e.printStackTrace();
187 | }
188 | }
189 | long time2 = System.currentTimeMillis();
190 | log.e("exitWorkThread cost time:" + (time2 - time1));
191 | mWorkThread = null;
192 | }
193 | }
194 |
195 |
196 | }
197 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/mediaserver/server/center/DMSWorkThread.java:
--------------------------------------------------------------------------------
1 | package com.github.mediaserver.server.center;
2 |
3 | import com.github.mediaserver.ServerApplication;
4 | import com.github.mediaserver.server.jni.DMSJniInterface;
5 | import com.github.mediaserver.util.CommonLog;
6 | import com.github.mediaserver.util.CommonUtil;
7 | import com.github.mediaserver.util.LogFactory;
8 | import android.content.Context;
9 |
10 |
11 | public class DMSWorkThread extends Thread implements IBaseEngine{
12 |
13 |
14 | private static final CommonLog log = LogFactory.createLog();
15 |
16 | private static final int CHECK_INTERVAL = 30 * 1000;
17 |
18 | private Context mContext = null;
19 | private boolean mStartSuccess = false;
20 | private boolean mExitFlag = false;
21 |
22 | private String mRootdir = "";
23 | private String mFriendName = "";
24 | private String mUUID = "";
25 | private ServerApplication mApplication;
26 |
27 | public DMSWorkThread(Context context){
28 | mContext = context;
29 | mApplication = ServerApplication.getInstance();
30 | }
31 |
32 | public void setFlag(boolean flag){
33 | mStartSuccess = flag;
34 | }
35 |
36 | public void setParam(String rootDir, String friendName, String uuid){
37 | mRootdir = rootDir;
38 | mFriendName = friendName;
39 | mUUID = uuid;
40 | mApplication.updateDevInfo(mRootdir, mFriendName, mUUID);
41 | }
42 |
43 | public void awakeThread(){
44 | synchronized (this) {
45 | notifyAll();
46 | }
47 | }
48 |
49 | public void exit(){
50 | mExitFlag = true;
51 | awakeThread();
52 | }
53 |
54 | @Override
55 | public void run() {
56 |
57 | log.e("DMSWorkThread run...");
58 |
59 | while(true)
60 | {
61 | if (mExitFlag){
62 | stopEngine();
63 | break;
64 | }
65 | refreshNotify();
66 | synchronized(this)
67 | {
68 | try
69 | {
70 | wait(CHECK_INTERVAL);
71 | }
72 | catch(Exception e)
73 | {
74 | e.printStackTrace();
75 | }
76 | }
77 | if (mExitFlag){
78 | stopEngine();
79 | break;
80 | }
81 | }
82 |
83 | log.e("DMSWorkThread over...");
84 |
85 | }
86 |
87 | public void refreshNotify(){
88 | if (!CommonUtil.checkNetworkState(mContext)){
89 | return ;
90 | }
91 |
92 | if (!mStartSuccess){
93 | stopEngine();
94 | try {
95 | Thread.sleep(200);
96 | } catch (InterruptedException e) {
97 | e.printStackTrace();
98 | }
99 | boolean ret = startEngine();
100 | if (ret){
101 | mStartSuccess = true;
102 | }
103 | }
104 |
105 | }
106 |
107 | @Override
108 | public boolean startEngine() {
109 | if (mFriendName.length() == 0){
110 | return false;
111 | }
112 |
113 | int ret = DMSJniInterface.startServer(mRootdir, mFriendName, mUUID);
114 |
115 | boolean result = (ret == 0 ? true : false);
116 | mApplication.setDevStatus(result);
117 | return result;
118 | }
119 |
120 | @Override
121 | public boolean stopEngine() {
122 | DMSJniInterface.stopServer();
123 | mApplication.setDevStatus(false);
124 | return true;
125 | }
126 |
127 | @Override
128 | public boolean restartEngine() {
129 | setFlag(false);
130 | awakeThread();
131 | return true;
132 | }
133 |
134 | }
135 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/mediaserver/server/center/IBaseEngine.java:
--------------------------------------------------------------------------------
1 | package com.github.mediaserver.server.center;
2 |
3 | public interface IBaseEngine {
4 |
5 | public boolean startEngine();
6 | public boolean stopEngine();
7 | public boolean restartEngine();
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/mediaserver/server/center/LocalConfigSharePreference.java:
--------------------------------------------------------------------------------
1 | package com.github.mediaserver.server.center;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 | import android.content.SharedPreferences.Editor;
6 |
7 | public class LocalConfigSharePreference {
8 |
9 | public static final String preference_name = "LocalConfigSharePreference";
10 | public static final String dev_name = "dev_name";
11 |
12 | public static boolean commintDevName(Context context, String devName){
13 |
14 | SharedPreferences sharedPreferences = context.getSharedPreferences(preference_name, 0);
15 | Editor editor = sharedPreferences.edit();
16 | editor.putString(dev_name, devName);
17 | editor.commit();
18 | return true;
19 | }
20 |
21 | public static String getDevName(Context context){
22 | SharedPreferences sharedPreferences = context.getSharedPreferences(preference_name, 0);
23 | String value = sharedPreferences.getString(dev_name, "geniusgithub");
24 | return value;
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/mediaserver/server/center/MediaServerProxy.java:
--------------------------------------------------------------------------------
1 | package com.github.mediaserver.server.center;
2 |
3 |
4 | import android.content.Context;
5 | import android.content.Intent;
6 |
7 | import com.github.mediaserver.ServerApplication;
8 | import com.github.mediaserver.server.DMSService;
9 | import com.github.mediaserver.util.CommonLog;
10 | import com.github.mediaserver.util.LogFactory;
11 |
12 | public class MediaServerProxy implements IBaseEngine{
13 |
14 | private static final CommonLog log = LogFactory.createLog();
15 |
16 | private static MediaServerProxy mInstance;
17 | private Context mContext;
18 |
19 | private MediaServerProxy(Context context) {
20 | mContext = context;
21 | }
22 |
23 | public static synchronized MediaServerProxy getInstance() {
24 | if (mInstance == null){
25 | mInstance = new MediaServerProxy(ServerApplication.getInstance());
26 | }
27 | return mInstance;
28 | }
29 |
30 | @Override
31 | public boolean startEngine() {
32 | Intent intent = new Intent(DMSService.START_SERVER_ENGINE);
33 | intent.setPackage(mContext.getPackageName());
34 | mContext.startService(intent);
35 | return true;
36 | }
37 |
38 | @Override
39 | public boolean stopEngine() {
40 | mContext.stopService(new Intent(mContext, DMSService.class));
41 | return true;
42 | }
43 |
44 | @Override
45 | public boolean restartEngine() {
46 | Intent intent = new Intent(DMSService.RESTART_SERVER_ENGINE);
47 | intent.setPackage(mContext.getPackageName());
48 | mContext.startService(intent);
49 | return true;
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/mediaserver/server/center/MediaStoreCenter.java:
--------------------------------------------------------------------------------
1 | package com.github.mediaserver.server.center;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.IOException;
5 | import java.io.InputStream;
6 | import java.io.InputStreamReader;
7 | import java.util.HashMap;
8 | import java.util.Map;
9 |
10 | import android.content.Context;
11 |
12 | import com.github.mediaserver.ServerApplication;
13 | import com.github.mediaserver.server.media.IMediaScanListener;
14 | import com.github.mediaserver.server.media.MediaScannerCenter;
15 | import com.github.mediaserver.util.CommonLog;
16 | import com.github.mediaserver.util.FileHelper;
17 | import com.github.mediaserver.util.LogFactory;
18 |
19 | public class MediaStoreCenter implements IMediaScanListener{
20 |
21 |
22 | private static final CommonLog log = LogFactory.createLog();
23 |
24 | private static MediaStoreCenter mInstance;
25 | private Context mContext;
26 |
27 |
28 | private String mShareRootPath = "";
29 | private String mImageFolderPath = "";
30 | private String mVideoFolderPath = "";
31 | private String mAudioFolderPath = "";
32 |
33 | private MediaScannerCenter mMediaScannerCenter;
34 | private Map mMediaStoreMap = new HashMap();
35 |
36 |
37 | private MediaStoreCenter(Context context) {
38 | mContext = context;
39 |
40 | initData();
41 | }
42 |
43 | public static synchronized MediaStoreCenter getInstance() {
44 | if (mInstance == null){
45 | mInstance = new MediaStoreCenter(ServerApplication.getInstance());
46 | }
47 | return mInstance;
48 | }
49 |
50 | private void initData(){
51 | mShareRootPath = mContext.getFilesDir().getAbsolutePath()+"/" + "rootFolder";
52 | mImageFolderPath = mShareRootPath + "/" + "Image";
53 | mVideoFolderPath = mShareRootPath + "/" + "Video";
54 | mAudioFolderPath = mShareRootPath + "/" + "Audio";
55 | mMediaScannerCenter = MediaScannerCenter.getInstance();
56 | }
57 |
58 | public String getRootDir(){
59 | return mShareRootPath;
60 | }
61 | public void clearAllData(){
62 | stopScanMedia();
63 | clearMediaCache();
64 | clearWebFolder();
65 | }
66 |
67 | public boolean createWebFolder(){
68 | boolean ret = FileHelper.createDirectory(mShareRootPath);
69 | if (!ret){
70 | return false;
71 | }
72 |
73 | FileHelper.createDirectory(mImageFolderPath);
74 | FileHelper.createDirectory(mVideoFolderPath);
75 | FileHelper.createDirectory(mAudioFolderPath);
76 |
77 | return true;
78 | }
79 |
80 | public boolean clearWebFolder(){
81 |
82 | long time = System.currentTimeMillis();
83 | boolean ret = FileHelper.deleteDirectory(mShareRootPath);
84 | long time1 = System.currentTimeMillis();
85 | log.e("clearWebFolder cost : " + (time1 - time));
86 | return ret;
87 | }
88 |
89 | public void clearMediaCache(){
90 | mMediaStoreMap.clear();
91 | }
92 |
93 | public void doScanMedia(){
94 | mMediaScannerCenter.startScanThread(this);
95 | }
96 |
97 | public void stopScanMedia(){
98 | mMediaScannerCenter.stopScanThread();
99 | while(!mMediaScannerCenter.isThreadOver()){
100 | try {
101 | Thread.sleep(100);
102 | } catch (InterruptedException e) {
103 | e.printStackTrace();
104 | }
105 | }
106 | }
107 |
108 | @Override
109 | public void mediaScan(int mediaType, String mediaPath, String mediaName) {
110 |
111 | switch (mediaType) {
112 | case MediaScannerCenter.AUDIO_TYPE:
113 | mapAudio(mediaPath, mediaName);
114 | break;
115 | case MediaScannerCenter.VIDEO_TYPE:
116 | mapVideo(mediaPath, mediaName);
117 | break;
118 | case MediaScannerCenter.IMAGE_TYPE:
119 | mapImage(mediaPath, mediaName);
120 | break;
121 | default:
122 | break;
123 | }
124 |
125 | }
126 |
127 |
128 | private void mapAudio( String mediaPath, String mediaName){
129 | String webPath = mAudioFolderPath + "/" + mediaName;
130 | mMediaStoreMap.put(mediaPath, webPath);
131 | softLinkMode(mediaPath, webPath);
132 | }
133 |
134 | private void mapVideo( String mediaPath, String mediaName){
135 | String webPath = mVideoFolderPath + "/" + mediaName;
136 | mMediaStoreMap.put(mediaPath, webPath);
137 | softLinkMode(mediaPath, webPath);
138 | }
139 |
140 | private void mapImage( String mediaPath, String mediaName){
141 | String webPath = mImageFolderPath + "/" + mediaName;
142 | mMediaStoreMap.put(mediaPath, webPath);
143 | softLinkMode(mediaPath, webPath);
144 | }
145 |
146 |
147 | private boolean softLinkMode(String localPath, String webPath){
148 | Process p;
149 | int status;
150 | try {
151 | long time = System.currentTimeMillis();
152 | String cmd = "ln -s " + localPath + " "+ webPath;
153 | p = Runtime.getRuntime().exec(cmd);
154 | releaseProcessStream(p);
155 |
156 | status = p.waitFor();
157 | if (status == 0) {
158 | return true;//success
159 | } else {
160 | log.e("status = " + status + ", run ln -s failed !localPath = " + localPath);
161 | return false;
162 | }
163 | }catch (Exception e) {
164 | log.e("Catch Exceptino run ln -s failed !localPath = " + localPath);
165 | return false;
166 | }
167 | }
168 |
169 | private void releaseProcessStream(Process p) throws IOException{
170 | InputStream stderr = p.getErrorStream();
171 | InputStreamReader isr = new InputStreamReader(stderr);
172 | BufferedReader br = new BufferedReader(isr);
173 | String line = null;
174 | while ( (line = br.readLine()) != null)
175 | System.out.println(line);
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/mediaserver/server/jni/DMSJniInterface.java:
--------------------------------------------------------------------------------
1 | package com.github.mediaserver.server.jni;
2 |
3 | import java.io.UnsupportedEncodingException;
4 |
5 | public class DMSJniInterface {
6 |
7 | static {
8 | System.loadLibrary("git-platinum");
9 | }
10 |
11 | public static native int startServer(byte[] rootDir,byte[] name ,byte[] uid);
12 | public static native int stopServer();
13 |
14 |
15 |
16 | public static native boolean enableLogPrint(boolean flag);
17 |
18 | //////////////////////////////////////////////////////////////////////////////////////////
19 | public static int startServer(String rootDir, String name ,String uid){
20 | if (rootDir == null){
21 | rootDir = "";
22 | }
23 | if (name == null){
24 | name = "";
25 | }
26 | if (uid == null){
27 | uid = "";
28 | }
29 | int ret = -1;
30 | try {
31 | ret = startServer(rootDir.getBytes("utf-8"), name.getBytes("utf-8"), uid.getBytes("utf-8"));
32 | } catch (UnsupportedEncodingException e) {
33 | e.printStackTrace();
34 | }
35 | return ret;
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/mediaserver/server/media/IMediaScanListener.java:
--------------------------------------------------------------------------------
1 | package com.github.mediaserver.server.media;
2 |
3 | public interface IMediaScanListener {
4 |
5 | public void mediaScan(int mediaType, String mediaPath, String mediaName);
6 | }
7 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/mediaserver/server/media/MediaScannerCenter.java:
--------------------------------------------------------------------------------
1 | package com.github.mediaserver.server.media;
2 |
3 | import android.content.Context;
4 | import android.database.Cursor;
5 | import android.provider.MediaStore;
6 |
7 | import com.github.mediaserver.ServerApplication;
8 | import com.github.mediaserver.server.center.MediaStoreCenter;
9 | import com.github.mediaserver.util.CommonLog;
10 | import com.github.mediaserver.util.FileHelper;
11 | import com.github.mediaserver.util.LogFactory;
12 |
13 | public class MediaScannerCenter {
14 |
15 | private static final CommonLog log = LogFactory.createLog();
16 |
17 | public static final int AUDIO_TYPE = 0;
18 | public static final int VIDEO_TYPE = 1;
19 | public static final int IMAGE_TYPE = 2;
20 |
21 |
22 |
23 | String AUDIO_PATH = MediaStore.Audio.AudioColumns.DATA;
24 | String AUDIO_DISPLAYHNAME = MediaStore.Audio.AudioColumns.DISPLAY_NAME;
25 | String AUDIO_COLUMN_STRS[] = {AUDIO_PATH, AUDIO_DISPLAYHNAME};
26 |
27 | String VIDEO_PATH = MediaStore.Video.VideoColumns.DATA;
28 | String VIDEO_DISPLAYHNAME = MediaStore.Video.VideoColumns.DISPLAY_NAME;
29 | String VIDEO_COLUMN_STRS[] = {VIDEO_PATH, VIDEO_DISPLAYHNAME};
30 |
31 | String IMAGE_PATH = MediaStore.Images.ImageColumns.DATA;
32 | String IMAGE_DISPLAYHNAME = MediaStore.Images.ImageColumns.DISPLAY_NAME;
33 | String IMAGE_COLUMN_STRS[] = {IMAGE_PATH, IMAGE_DISPLAYHNAME};
34 |
35 |
36 | private static MediaScannerCenter mInstance;
37 | private Context mContext;
38 |
39 | private ScanMediaThread mediaThread;
40 |
41 | private MediaScannerCenter(Context context) {
42 | mContext = context;
43 |
44 | initData();
45 | }
46 |
47 | public static synchronized MediaScannerCenter getInstance() {
48 | if (mInstance == null){
49 | mInstance = new MediaScannerCenter(ServerApplication.getInstance());
50 | }
51 | return mInstance;
52 | }
53 |
54 | private void initData(){
55 |
56 |
57 | }
58 |
59 |
60 | public synchronized boolean startScanThread(IMediaScanListener listener){
61 | if (mediaThread == null || !mediaThread.isAlive()){
62 | mediaThread = new ScanMediaThread(listener);
63 | mediaThread.start();
64 | }
65 |
66 | return true;
67 | }
68 |
69 | public synchronized void stopScanThread(){
70 | if (mediaThread != null){
71 | if (mediaThread.isAlive()){
72 | mediaThread.exit();
73 | }
74 | mediaThread = null;
75 | }
76 | }
77 |
78 | public synchronized boolean isThreadOver(){
79 | if (mediaThread != null && mediaThread.isAlive()){
80 | return false;
81 | }
82 |
83 | return true;
84 | }
85 |
86 | private boolean scanMusic(IMediaScanListener listener, ICancelScanMedia cancelObser) throws Exception {
87 |
88 | Cursor cursor = mContext.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
89 | AUDIO_COLUMN_STRS,
90 | null,
91 | null,
92 | AUDIO_DISPLAYHNAME);
93 |
94 | if (cursor != null)
95 | {
96 | int count = cursor.getCount();
97 | if (count != 0)
98 | {
99 | int _name_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME);
100 | int _dir_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
101 | if (cursor.moveToFirst()) {
102 | do {
103 | if (cancelObser.ifCancel()){
104 | return false;
105 | }
106 | String srcpath = cursor.getString(_dir_index);
107 | String name = cursor.getString(_name_index);
108 | listener.mediaScan(AUDIO_TYPE, srcpath, name);
109 |
110 | } while (cursor.moveToNext());
111 | }
112 | }
113 | cursor.close();
114 | return true;
115 | }
116 |
117 | return false;
118 | }
119 |
120 | private boolean scanVideo(IMediaScanListener listener, ICancelScanMedia cancelObser) throws Exception {
121 |
122 | Cursor cursor = mContext.getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
123 | VIDEO_COLUMN_STRS,
124 | null,
125 | null,
126 | VIDEO_DISPLAYHNAME);
127 |
128 | if (cursor != null)
129 | {
130 | int count = cursor.getCount();
131 | if (count != 0)
132 | {
133 | int _name_index = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME);
134 | int _dir_index = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
135 | if (cursor.moveToFirst()) {
136 | do {
137 | if (cancelObser.ifCancel()){
138 | return false;
139 | }
140 | String srcpath = cursor.getString(_dir_index);
141 | String name = cursor.getString(_name_index);
142 | listener.mediaScan(VIDEO_TYPE, srcpath, name);
143 | } while (cursor.moveToNext());
144 | }
145 | }
146 | cursor.close();
147 | return true;
148 | }
149 |
150 | return false;
151 | }
152 |
153 | private boolean scanImage(IMediaScanListener listener, ICancelScanMedia cancelObser) throws Exception {
154 |
155 | Cursor cursor = mContext.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
156 | IMAGE_COLUMN_STRS,
157 | null,
158 | null,
159 | IMAGE_DISPLAYHNAME);
160 |
161 | if (cursor != null)
162 | {
163 | int count = cursor.getCount();
164 | if (count != 0)
165 | {
166 | int _name_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME);
167 | int _dir_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
168 | if (cursor.moveToFirst()) {
169 | do {
170 | if (cancelObser.ifCancel()){
171 | return false;
172 | }
173 | String srcpath = cursor.getString(_dir_index);
174 | String name = cursor.getString(_name_index);
175 | listener.mediaScan(IMAGE_TYPE, srcpath, name);
176 |
177 | } while (cursor.moveToNext());
178 | }
179 | }
180 | cursor.close();
181 | return true;
182 | }
183 |
184 | return false;
185 | }
186 |
187 |
188 | public class ScanMediaThread extends Thread implements ICancelScanMedia{
189 |
190 | IMediaScanListener mListener;
191 | boolean exitFlag = false;
192 |
193 | public ScanMediaThread(IMediaScanListener listener){
194 | mListener = listener;
195 | }
196 |
197 | public void exit(){
198 | exitFlag = true;
199 | }
200 |
201 | @Override
202 | public void run() {
203 |
204 | try {
205 | scanMusic(mListener, this);
206 | scanVideo(mListener, this);
207 | scanImage(mListener, this);
208 | } catch (Exception e) {
209 | e.printStackTrace();
210 | }
211 |
212 | super.run();
213 | }
214 |
215 | @Override
216 | public boolean ifCancel() {
217 | return exitFlag;
218 | }
219 | }
220 |
221 |
222 | public interface ICancelScanMedia{
223 | public boolean ifCancel();
224 | }
225 |
226 |
227 | }
228 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/mediaserver/util/CommonLog.java:
--------------------------------------------------------------------------------
1 | package com.github.mediaserver.util;
2 |
3 | import android.util.Log;
4 |
5 | public class CommonLog {
6 | private String tag = "CommonLog";
7 | public static int logLevel = Log.VERBOSE;
8 | public static boolean isDebug = true;
9 |
10 | public CommonLog() { }
11 |
12 | public CommonLog(String tag) {
13 | this.tag = tag;
14 | }
15 |
16 | public void setTag(String tag) {
17 | this.tag = tag;
18 | }
19 |
20 | private String getFunctionName() {
21 | StackTraceElement[] sts = Thread.currentThread().getStackTrace();
22 |
23 | if (sts == null) {
24 | return null;
25 | }
26 |
27 |
28 | for (StackTraceElement st:sts) {
29 | if (st.isNativeMethod()) {
30 | continue;
31 | }
32 |
33 | if (st.getClassName().equals(Thread.class.getName())) {
34 | continue;
35 | }
36 |
37 | if (st.getClassName().equals(this.getClass().getName())) {
38 | continue;
39 | }
40 |
41 | return "["+Thread.currentThread().getId()+": "+st.getFileName()+":"+st.getLineNumber()+"]";
42 | }
43 |
44 | return null;
45 | }
46 |
47 | public void info(Object str) {
48 | if (logLevel <= Log.INFO) {
49 | String name = getFunctionName();
50 | String ls=(name==null?str.toString():(name+" - "+str));
51 | Log.i(tag, ls);
52 | }
53 | }
54 |
55 | public void i(Object str) {
56 | if (isDebug) {
57 | info(str);
58 | }
59 | }
60 |
61 | public void verbose(Object str) {
62 | if (logLevel <= Log.VERBOSE) {
63 | String name = getFunctionName();
64 | String ls=(name==null?str.toString():(name+" - "+str));
65 | Log.v(tag, ls);
66 | }
67 | }
68 |
69 | public void v(Object str) {
70 | if (isDebug) {
71 | verbose(str);
72 | }
73 | }
74 |
75 | public void warn(Object str) {
76 | if (logLevel <= Log.WARN) {
77 | String name = getFunctionName();
78 | String ls=(name==null?str.toString():(name+" - "+str));
79 | Log.w(tag, ls);
80 | }
81 | }
82 |
83 | public void w(Object str) {
84 | if (isDebug) {
85 | warn(str);
86 | }
87 | }
88 |
89 | public void error(Object str) {
90 | if (logLevel <= Log.ERROR) {
91 | String name = getFunctionName();
92 | String ls=(name==null?str.toString():(name+" - "+str));
93 | Log.e(tag, ls);
94 | }
95 | }
96 |
97 | public void error(Exception ex) {
98 | if (logLevel <= Log.ERROR) {
99 | StringBuffer sb = new StringBuffer();
100 | String name = getFunctionName();
101 | StackTraceElement[] sts = ex.getStackTrace();
102 |
103 | if (name != null) {
104 | sb.append(name+" - "+ex+"\r\n");
105 | } else {
106 | sb.append(ex+"\r\n");
107 | }
108 |
109 | if (sts != null && sts.length > 0) {
110 | for (StackTraceElement st:sts) {
111 | if (st != null) {
112 | sb.append("[ "+st.getFileName()+":"+st.getLineNumber()+" ]\r\n");
113 | }
114 | }
115 | }
116 |
117 | Log.e(tag, sb.toString());
118 | }
119 | }
120 |
121 | public void e(Object str) {
122 | if (isDebug) {
123 | error(str);
124 | }
125 | }
126 |
127 | public void e(Exception ex) {
128 | if (isDebug) {
129 | error(ex);
130 | }
131 | }
132 |
133 | public void debug(Object str) {
134 | if (logLevel <= Log.DEBUG) {
135 | String name = getFunctionName();
136 | String ls = (name == null?str.toString():(name+" - "+str));
137 | Log.d(tag, ls);
138 | }
139 | }
140 |
141 | public void d(Object str) {
142 | if (isDebug) {
143 | debug(str);
144 | }
145 | }
146 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/mediaserver/util/CommonUtil.java:
--------------------------------------------------------------------------------
1 | package com.github.mediaserver.util;
2 |
3 |
4 |
5 | import java.io.InputStream;
6 | import java.net.InetAddress;
7 | import java.net.NetworkInterface;
8 | import java.net.SocketException;
9 | import java.util.Enumeration;
10 |
11 |
12 | import android.content.Context;
13 | import android.content.pm.PackageInfo;
14 | import android.content.pm.PackageManager;
15 | import android.media.AudioManager;
16 | import android.media.MediaPlayer;
17 | import android.net.ConnectivityManager;
18 | import android.net.NetworkInfo;
19 | import android.net.NetworkInfo.State;
20 | import android.net.TrafficStats;
21 | import android.net.wifi.WifiInfo;
22 | import android.net.wifi.WifiManager;
23 | import android.net.wifi.WifiManager.MulticastLock;
24 | import android.os.Environment;
25 | import android.view.Display;
26 | import android.view.WindowManager;
27 | import android.widget.Toast;
28 |
29 | public class CommonUtil {
30 |
31 | private static final CommonLog log = LogFactory.createLog();
32 |
33 | public static boolean hasSDCard() {
34 | String status = Environment.getExternalStorageState();
35 | if (!status.equals(Environment.MEDIA_MOUNTED)) {
36 | return false;
37 | }
38 | return true;
39 | }
40 |
41 | public static String getRootFilePath() {
42 | if (hasSDCard()) {
43 | return Environment.getExternalStorageDirectory().getAbsolutePath() + "/";// filePath:/sdcard/
44 | } else {
45 | return Environment.getDataDirectory().getAbsolutePath() + "/data/"; // filePath: /data/data/
46 | }
47 | }
48 |
49 | public static boolean checkNetworkState(Context context){
50 | boolean netstate = false;
51 | ConnectivityManager connectivity = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
52 | if(connectivity != null)
53 | {
54 | NetworkInfo[] info = connectivity.getAllNetworkInfo();
55 | if (info != null) {
56 | for (int i = 0; i < info.length; i++)
57 | {
58 | if (info[i].getState() == NetworkInfo.State.CONNECTED)
59 | {
60 | netstate = true;
61 | break;
62 | }
63 | }
64 | }
65 | }
66 | return netstate;
67 | }
68 |
69 | public static String getLocalMacAddress(Context mc){
70 | String defmac = "00:00:00:00:00:00";
71 | InputStream input = null;
72 | String wifimac = getWifiMacAddress(mc);
73 | if(null != wifimac){
74 | if(!wifimac.equals(defmac))
75 | return wifimac;
76 | }
77 | try{
78 |
79 | ProcessBuilder builder = new ProcessBuilder( "busybox","ifconfig");
80 | Process process = builder.start();
81 | input = process.getInputStream();
82 |
83 |
84 |
85 | byte[] b = new byte[1024];
86 | StringBuffer buffer = new StringBuffer();
87 | while(input.read(b)>0){
88 | buffer.append(new String(b));
89 | }
90 | String value = buffer.substring(0);
91 | String systemFlag ="HWaddr ";
92 | int index = value.indexOf(systemFlag);
93 | //List address = new ArrayList ();
94 | if(0"+destUri);
248 | return false;
249 | }
250 |
251 | // check output uri
252 | String path = null;
253 | Uri uri = null;
254 |
255 | String lwUri = destUri.toLowerCase();
256 | if (lwUri.startsWith("content://")) {
257 | uri = Uri.parse(destUri);
258 | } else if (lwUri.startsWith("file://")) {
259 | uri = Uri.parse(destUri);
260 | path = uri.getPath();
261 | } else {
262 | path = destUri;
263 | }
264 |
265 | // open output
266 | if (null != path) {
267 | File fl = new File(path);
268 | String pth = path.substring(0, path.lastIndexOf("/"));
269 | File pf = new File(pth);
270 |
271 | if (pf.exists() && !pf.isDirectory()) {
272 | pf.delete();
273 | }
274 |
275 | pf = new File(pth+File.separator);
276 |
277 | if (!pf.exists()) {
278 | if (!pf.mkdirs()) {
279 | log.e("Can't make dirs, path=" + pth);
280 | }
281 | }
282 |
283 | pf = new File(path);
284 | if (pf.exists()) {
285 | if (pf.isDirectory()) deleteDirectory(path);
286 | else pf.delete();
287 | }
288 |
289 | os = new FileOutputStream(path);
290 | fl.setLastModified(System.currentTimeMillis());
291 | } else {
292 | os = new ParcelFileDescriptor.AutoCloseOutputStream(cr.openFileDescriptor(uri, "w"));
293 | }
294 |
295 | // copy file
296 | byte[] dat = new byte[1024];
297 | int i = is.read(dat);
298 | while(-1 != i) {
299 | os.write(dat, 0, i);
300 | i = is.read(dat);
301 | }
302 |
303 | is.close();
304 | is = null;
305 |
306 | os.flush();
307 | os.close();
308 | os = null;
309 |
310 | return true;
311 |
312 | } catch(Exception ex) {
313 | log.e("Exception, ex: " + ex.toString());
314 | } finally {
315 | if(null != is) {
316 | try{is.close();} catch(Exception ex) {};
317 | }
318 | if(null != os) {
319 | try{os.close();} catch(Exception ex) {};
320 | }
321 | }
322 | return false;
323 | }
324 |
325 | public static byte[] readAll(InputStream is) throws Exception {
326 | ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
327 | byte[] buf = new byte[1024];
328 | int c = is.read(buf);
329 | while(-1 != c) {
330 | baos.write(buf, 0, c);
331 | c = is.read(buf);
332 | }
333 | baos.flush();
334 | baos.close();
335 | return baos.toByteArray();
336 | }
337 |
338 | public static byte[] readFile(Context ctx, Uri uri) {
339 | if(null == ctx || null == uri) {
340 | log.e("Invalid param. ctx: "+ctx+", uri: "+uri);
341 | return null;
342 | }
343 |
344 | InputStream is = null;
345 | String scheme = uri.getScheme().toLowerCase();
346 | if (scheme.equals("file")) {
347 | is = readFile(uri.getPath());
348 | }
349 |
350 | try {
351 | is = ctx.getContentResolver().openInputStream(uri);
352 | if(null == is) {
353 | return null;
354 | }
355 |
356 | byte[] bret = readAll(is);
357 | is.close(); is = null;
358 |
359 | return bret;
360 | } catch(FileNotFoundException fne) {
361 | log.e("FilNotFoundException, ex: " + fne.toString());
362 | } catch(Exception ex) {
363 | log.e("Exception, ex: " + ex.toString());
364 | } finally {
365 | if (null != is) {
366 | try {is.close();} catch(Exception ex) {};
367 | }
368 | }
369 | return null;
370 | }
371 |
372 | public static boolean writeFile(String filePath, byte[] content) {
373 | if(null == filePath || null == content) {
374 | log.e("Invalid param. filePath: "+filePath+", content: "+content);
375 | return false;
376 | }
377 |
378 | FileOutputStream fos = null;
379 | try{
380 | String pth = filePath.substring(0, filePath.lastIndexOf("/"));
381 | File pf = null;
382 | pf = new File(pth);
383 | if(pf.exists() && !pf.isDirectory()) {
384 | pf.delete();
385 | }
386 | pf = new File(filePath);
387 | if(pf.exists()) {
388 | if(pf.isDirectory()) FileHelper.deleteDirectory(filePath);
389 | else pf.delete();
390 | }
391 |
392 | pf = new File(pth+File.separator);
393 | if (!pf.exists()) {
394 | if (!pf.mkdirs()) {
395 | log.e("Can't make dirs, path=" + pth);
396 | }
397 | }
398 |
399 | fos = new FileOutputStream(filePath);
400 | fos.write(content);
401 | fos.flush();
402 | fos.close(); fos = null;
403 | pf.setLastModified(System.currentTimeMillis());
404 |
405 | return true;
406 |
407 | } catch(Exception ex) {
408 | log.e("Exception, ex: " + ex.toString());
409 | } finally {
410 | if(null != fos) {
411 | try { fos.close(); } catch(Exception ex) {};
412 | }
413 | }
414 | return false;
415 | }
416 |
417 | /*************ZIP file operation***************/
418 | public static boolean readZipFile(String zipFileName, StringBuffer crc) {
419 | try {
420 | ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFileName));
421 | ZipEntry entry;
422 | while ((entry = zis.getNextEntry()) != null) {
423 | long size = entry.getSize();
424 | crc.append(entry.getCrc() + ", size: " + size);
425 | }
426 | zis.close();
427 | } catch (Exception ex) {
428 | log.e("Exception: " + ex.toString());
429 | return false;
430 | }
431 | return true;
432 | }
433 |
434 | public static byte[] readGZipFile (String zipFileName) {
435 | if (fileIsExist(zipFileName)) {
436 | log.i("zipFileName: " + zipFileName);
437 | try {
438 | FileInputStream fin = new FileInputStream(zipFileName);
439 | int size;
440 | byte[] buffer = new byte[1024];
441 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
442 | while ((size = fin.read(buffer, 0, buffer.length)) != -1) {
443 | baos.write(buffer, 0, size);
444 | }
445 | return baos.toByteArray();
446 | } catch (Exception ex) {
447 | log.i("read zipRecorder file error");
448 | }
449 | }
450 | return null;
451 | }
452 |
453 | public static boolean zipFile(String baseDirName, String fileName, String targerFileName) throws IOException {
454 | if (baseDirName == null || "".equals(baseDirName)) {
455 | return false;
456 | }
457 | File baseDir = new File(baseDirName);
458 | if (!baseDir.exists() || !baseDir.isDirectory()) {
459 | return false;
460 | }
461 |
462 | String baseDirPath = baseDir.getAbsolutePath();
463 | File targerFile = new File(targerFileName);
464 | ZipOutputStream out = new ZipOutputStream(new FileOutputStream(targerFile));
465 | File file = new File(baseDir, fileName);
466 |
467 | boolean zipResult = false;
468 | if (file.isFile()) {
469 | zipResult = fileToZip(baseDirPath, file, out);
470 | } else {
471 | zipResult = dirToZip(baseDirPath, file, out);
472 | }
473 | out.close();
474 | return zipResult;
475 | }
476 |
477 | public static boolean unZipFile(String fileName, String unZipDir) throws Exception {
478 | File f = new File(unZipDir);
479 |
480 | if (!f.exists()) {
481 | f.mkdirs();
482 | }
483 |
484 | BufferedInputStream is = null;
485 | ZipEntry entry;
486 | ZipFile zipfile = new ZipFile(fileName);
487 | Enumeration> enumeration = zipfile.entries();
488 | byte data[] = new byte[FILE_BUFFER_SIZE];
489 | log.i("unZipDir: " + unZipDir);
490 |
491 | while (enumeration.hasMoreElements()) {
492 | entry = (ZipEntry)enumeration.nextElement();
493 |
494 | if (entry.isDirectory()) {
495 | File f1 = new File(unZipDir + "/" + entry.getName());
496 | log.i("entry.isDirectory XXX " + f1.getPath());
497 | if (!f1.exists()) {
498 | f1.mkdirs();
499 | }
500 | } else {
501 | is = new BufferedInputStream(zipfile.getInputStream(entry));
502 | int count;
503 | String name = unZipDir + "/" + entry.getName();
504 | RandomAccessFile m_randFile = null;
505 | File file = new File(name);
506 | if (file.exists()) {
507 | file.delete();
508 | }
509 |
510 | file.createNewFile();
511 | m_randFile = new RandomAccessFile(file, "rw");
512 | int begin = 0;
513 |
514 | while ((count = is.read(data, 0, FILE_BUFFER_SIZE)) != -1) {
515 | try {
516 | m_randFile.seek(begin);
517 | } catch (Exception ex) {
518 | log.e("exception, ex: " + ex.toString());
519 | }
520 |
521 | m_randFile.write(data, 0, count);
522 | begin = begin + count;
523 | }
524 |
525 | file.delete();
526 | m_randFile.close();
527 | is.close();
528 | }
529 | }
530 |
531 | return true;
532 | }
533 |
534 | private static boolean fileToZip(String baseDirPath, File file, ZipOutputStream out) throws IOException {
535 | FileInputStream in = null;
536 | ZipEntry entry = null;
537 |
538 | byte[] buffer = new byte[FILE_BUFFER_SIZE];
539 | int bytes_read;
540 | try {
541 | in = new FileInputStream(file);
542 | entry = new ZipEntry(getEntryName(baseDirPath, file));
543 | out.putNextEntry(entry);
544 |
545 | while ((bytes_read = in.read(buffer)) != -1) {
546 | out.write(buffer, 0, bytes_read);
547 | }
548 | out.closeEntry();
549 | in.close();
550 | } catch (IOException e) {
551 | log.e("Exception, ex: " + e.toString());
552 | return false;
553 | } finally {
554 | if (out != null) {
555 | out.closeEntry();
556 | }
557 |
558 | if (in != null) {
559 | in.close();
560 | }
561 | }
562 | return true;
563 | }
564 |
565 | private static boolean dirToZip(String baseDirPath, File dir, ZipOutputStream out) throws IOException {
566 | if (!dir.isDirectory()) {
567 | return false;
568 | }
569 |
570 | File[] files = dir.listFiles();
571 | if (files.length == 0) {
572 | ZipEntry entry = new ZipEntry(getEntryName(baseDirPath, dir));
573 |
574 | try {
575 | out.putNextEntry(entry);
576 | out.closeEntry();
577 | } catch (IOException e) {
578 | log.e("Exception, ex: " + e.toString());
579 | }
580 | }
581 |
582 | for (int i = 0; i < files.length; i ++) {
583 | if (files[i].isFile()) {
584 | fileToZip(baseDirPath, files[i], out);
585 | } else {
586 | dirToZip(baseDirPath, files[i], out);
587 | }
588 | }
589 | return true;
590 | }
591 |
592 | private static String getEntryName(String baseDirPath, File file) {
593 | if (!baseDirPath.endsWith(File.separator)) {
594 | baseDirPath = baseDirPath + File.separator;
595 | }
596 |
597 | String filePath = file.getAbsolutePath();
598 | if (file.isDirectory()) {
599 | filePath = filePath + "/";
600 | }
601 |
602 | int index = filePath.indexOf(baseDirPath);
603 | return filePath.substring(index + baseDirPath.length());
604 | }
605 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/mediaserver/util/LogFactory.java:
--------------------------------------------------------------------------------
1 | package com.github.mediaserver.util;
2 |
3 |
4 | public class LogFactory {
5 | private static final String TAG = "MediaServer";
6 | private static CommonLog log = null;
7 |
8 | public static CommonLog createLog() {
9 | if (log == null) {
10 | log = new CommonLog();
11 | }
12 |
13 | log.setTag(TAG);
14 | return log;
15 | }
16 |
17 | public static CommonLog createLog(String tag) {
18 | if (log == null) {
19 | log = new CommonLog();
20 | }
21 |
22 | if (tag == null || tag.length() < 1) {
23 | log.setTag(TAG);
24 | } else {
25 | log.setTag(tag);
26 | }
27 | return log;
28 | }
29 | }
--------------------------------------------------------------------------------
/app/src/main/jniLibs/armeabi/libgit-platinum.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/jniLibs/armeabi/libgit-platinum.so
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/main_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable-hdpi/main_bg.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_normal.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable/button_normal.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_pressed.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable/button_pressed.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/input_disabled.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable/input_disabled.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/input_normal.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable/input_normal.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/input_pressed.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable/input_pressed.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/app/src/main/res/drawable/logo.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/selector_btn.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/selector_edit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
17 |
18 |
19 |
20 |
21 |
22 |
27 |
28 |
36 |
37 |
38 |
46 |
47 |
48 |
56 |
57 |
58 |
59 |
60 |
61 |
68 |
69 |
77 |
78 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
99 |
100 |
101 |
109 |
110 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | MediaServer
5 | Hello world!
6 | Settings
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/test/java/com/github/mediaserver/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.github.mediaserver;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.5.0'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/geniusgithub/MediaServer/1221927f93d993167a5f007358b165b0283f040f/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------