练习代码

/*
3月26日
Android异步消息机制
Handler的常规使用方式
*/

/**
 * 测试Activity,主要用于测试异步消息(Handler)的使用方式
 */
public class MainActivity extends AppCompatActivity {
    public static final String TAG = MainActivity.class.getSimpleName();
    private TextView texttitle = null;
    /**
     * 在主线程中定义Handler,并实现对应的handleMessage方法
     * 一般handler的使用方式都是在主线程中定义Handler,然后在子线程中调用mHandler.sendEmptyMessage();方法
     */
    public static Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 101) {
                Log.i(TAG, "接收到handler消息...");
            }
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        texttitle = (TextView) findViewById(R.id.texttitle);
        texttitle.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread() {
                    @Override
                    public void run() {
                        // 在子线程中发送异步消息
                        mHandler.sendEmptyMessage(101);
                    }
                }.start();
            }
        });
    }
}
/*
3月27日
Android异步消息机制
在子线程中定义Handler
*/

/**
 * 定义texttitle的点击事件处理
 * 在初始化Handler对象之前需要调用Looper.prepare()方法
 */
texttitle.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread() {
                    @Override
                    public void run() {
                        Looper.prepare();
                        Handler mHandler = new Handler() {
                            @Override
                            public void handleMessage(Message msg) {
                                if (msg.what == 101) {
                                    Log.i(TAG, "在子线程中定义Handler,并接收到消息。。。");
                                }
                            }
                        };
                    }
                }.start();
            }
        });
/*
3月28日
Android异步消息机制
App初始化的时候执行ActivityThread的main方法
*/

public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
        SamplingProfilerIntegration.start();
        CloseGuard defaults to true and can be quite spammy.  We
        disable it here, but selectively enable it later (via
        StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);
        Environment.initForCurrentUser();
        Set the reporter for event logging in libcore
        EventLogger.setReporter(new EventLoggingReporter());
        AndroidKeyStoreProvider.install();
        //Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);
        Process.setArgV0("<pre-initialized>");
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
/*
3月29日
Android异步消息机制
Handler的标准写法
*/

Looper.prepare();
Handler mHandler = new Handler() {
   @Override
   public void handleMessage(Message msg) {
      if (msg.what == 101) {
         Log.i(TAG, "在子线程中定义Handler,并接收到消息。。。");
       }
   }
};
Looper.loop();
/*
3月30日
Android异步消息机制
查看Looper.prepare()方法
*/

   sThreadLocal.get() will return null unless you've called prepare().
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
/** Initialize the current thread as a looper.
      * This gives you a chance to create handlers that then reference
      * this looper, before actually starting the loop. Be sure to call
      * {@link #loop()} after calling this method, and end it by calling
      * {@link #quit()}.
      */
    public static void prepare() {
        prepare(true);
    }
    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }
//Looper对象的构造方法,可以看到在其构造方法中初始化了一个MessageQueue对象
   private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }
/*
3月31日
Android异步消息机制
查看Handler对象的构造方法
*/

public Handler(Callback callback, boolean async) {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }
    //查看handler.sendMessage(msg)方法
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }
/*
4月1日
Android异步消息机制
查看messagequeue对象的enqueueMessage方法
*/

boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }
        synchronized (this) {
            if (mQuitting) {
                IllegalStateException e = new IllegalStateException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w(TAG, e.getMessage(), e);
                msg.recycle();
                return false;
            }
            msg.markInUse();
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                // Inserted within the middle of the queue.  Usually we don't have to wake
                // up the event queue unless there is a barrier at the head of the queue
                // and the message is the earliest asynchronous message in the queue.
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }
            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }
/*
4月2日
Android异步消息机制
查看Looper.Loop()方法
*/

/**
     * Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the loop.
     */
    public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;
        /Make sure the identity of this thread is that of the local process,
        and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();
        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            // This must be in a local variable, in case a UI event sets the logger
            Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }
            msg.target.dispatchMessage(msg);
            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }
            Make sure that during the course of dispatching the
            identity of the thread wasn't corrupted.
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }
            msg.recycleUnchecked();
        }
    }
/*
4月3日
Android异步消息机制
Looper.loop()方法里起了一个死循环,不断的判断MessageQueue中的消息是否为空,如果为空则直接return掉,然后执行queue.next()方法:
*/

Message next() {
        // Return here if the message loop has already quit and been disposed.
        // This can happen if the application tries to restart a looper after quit
        // which is not supported.
        final long ptr = mPtr;
        if (ptr == 0) {
            return null;
        }
        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        int nextPollTimeoutMillis = 0;
        for (;;) {
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }
            nativePollOnce(ptr, nextPollTimeoutMillis);
           synchronized (this) {
                // Try to retrieve the next message.  Return if found.
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
                if (msg != null && msg.target == null) {
                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
                if (msg != null) {
                    if (now < msg.when) {
                        // Next message is not ready.  Set a timeout to wake up when it is ready.
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
/*
4月4日
Android异步消息机制
Looper.loop()方法里起了一个死循环,不断的判断MessageQueue中的消息是否为空,如果为空则直接return掉,然后执行queue.next()方法:
*/


                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    // No more messages.
                    nextPollTimeoutMillis = -1;
                }
                // Process the quit message now that all pending messages have been handled.
                if (mQuitting) {
                    dispose();
                    return null;
                }
                // If first time idle, then get the number of idlers to run.
                // Idle handles only run if the queue is empty or if the first message
                // in the queue (possibly a barrier) is due to be handled in the future.
                if (pendingIdleHandlerCount < 0
                        && (mMessages == null || now < mMessages.when)) {
                    pendingIdleHandlerCount = mIdleHandlers.size();
                }
                if (pendingIdleHandlerCount <= 0) {
                    // No idle handlers to run.  Loop and wait some more.
                    mBlocked = true;
                    continue;
                }
                if (mPendingIdleHandlers == null) {
                    mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
                }
                mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
            }
/*
4月5日
Android异步消息机制
Looper.loop()方法里起了一个死循环,不断的判断MessageQueue中的消息是否为空,如果为空则直接return掉,然后执行queue.next()方法:
*/

            Run the idle handlers.
            We only ever reach this code block during the first iteration.
            for (int i = 0; i < pendingIdleHandlerCount; i++) {
                final IdleHandler idler = mPendingIdleHandlers[i];
                mPendingIdleHandlers[i] = null; // release the reference to the handler
                boolean keep = false;
                try {
                    keep = idler.queueIdle();
                } catch (Throwable t) {
                    Log.wtf(TAG, "IdleHandler threw exception", t);
                }
                if (!keep) {
                    synchronized (this) {
                        mIdleHandlers.remove(idler);
                    }
                }
            }
            // Reset the idle handler count to 0 so we do not run them again.
            pendingIdleHandlerCount = 0;
            // While calling an idle handler, a new message could have been delivered
            // so go back and look again for a pending message without waiting.
            nextPollTimeoutMillis = 0;
        }
    }
/*
4月6日
Android异步消息机制
查看Handler类的dispatchMessage方法
*/

/**
     * Handle system messages here.
     */
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }
/*
4月7日
Android异步消息机制
总结
*/

主线程中定义Handler,直接执行:
Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
               super.handleMessage(msg);
        }
};
在子线程中定义Handler,则标准的写法为:
// 初始化该线程Looper,MessageQueue,执行且只能执行一次
                Looper.prepare();
                // 初始化Handler对象,内部关联Looper对象
                Handler mHandler = new Handler() {
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                    }
                };
                // 启动消息队列出栈死循环
                Looper.loop();
Handler的post方法:
public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }
view的post方法:
public boolean post(Runnable action) {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            return attachInfo.mHandler.post(action);
        }
        // Assume that post will succeed later
        ViewRootImpl.getRunQueue().post(action);
        return true;
activity的runOnUiThread方法:
public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }
/*
4月10日
异步任务AsyncTask
AsyncTask的基本使用
*/

/**
 * 自定义AsyncTask对象
 */
class MAsyncTask extends AsyncTask<Integer, Integer, Integer> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            Log.i(TAG, "onPreExecute...(开始执行后台任务之前)");
        }


        @Override
        protected void onPostExecute(Integer i) {
            super.onPostExecute(i);
            Log.i("TAG", "onPostExecute...(开始执行后台任务之后)");
        }


        @Override
        protected Integer doInBackground(Integer... params) {
            Log.i(TAG, "doInBackground...(开始执行后台任务)");
            return 0;
        }
    }
/*
4月11日
异步任务AsyncTask
查看异步任务的构造方法
*/

     /**
     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     */
    public AsyncTask() {
        mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                mTaskInvoked.set(true);
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                //noinspection unchecked
                Result result = doInBackground(mParams);
                Binder.flushPendingCommands();
                return postResult(result);
            }
        };
        mFuture = new FutureTask<Result>(mWorker) {
            @Override
            protected void done() {
                try {
                    postResultIfNotInvoked(get());
                } catch (InterruptedException e) {
                    android.util.Log.w(LOG_TAG, e);
                } catch (ExecutionException e) {
                    throw new RuntimeException("An error occurred while executing doInBackground()",
                            e.getCause());
                } catch (CancellationException e) {
                    postResultIfNotInvoked(null);
                }
            }
        };
    }
/*
4月13日
异步任务AsyncTask
测试在子线程中通过MAsyncTask执行异步操作
*/

/**
 * 测试代码,测试在子线程中通过MAsyncTask执行异步操作
 */
new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Log.i("tag", Thread.currentThread().getId() + "");
                        new MAsyncTask().execute();
                    }
                }).start();
                Log.i("tag", "mainThread:" + Thread.currentThread().getId() + "");
/*
4月14日
异步任务AsyncTask
execute方法内部调用了executeOnExecutor方法
*/

@MainThread
    public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
            Params... params) {
        if (mStatus != Status.PENDING) {
            switch (mStatus) {
                case RUNNING:
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task is already running.");
                case FINISHED:
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task has already been executed "
                            + "(a task can be executed only once)");
            }
        }
        mStatus = Status.RUNNING;
        onPreExecute();
        mWorker.mParams = params;
        exec.execute(mFuture);
        return this;
    }
/*
4月14日
异步任务AsyncTask
执行了execute方法之后,如果再次执行就会进入这里的if条件判断并抛出异常
*/

final MAsyncTask mAsyncTask = new MAsyncTask();
        title.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /*MLog.e("you have clicked the title textview!!!");
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                startActivityForResult(intent, 101);*/
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Log.i("tag", Thread.currentThread().getId() + "");
                        mAsyncTask
                                .execute();
                    }
                }).start();
                Log.i("tag", "mainThread:" + Thread.currentThread().getId() + "");
            }
        });
/*
4月15日
异步任务AsyncTask
查看SerialExecutor的具体实现
*/

private static class SerialExecutor implements Executor {
        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
        Runnable mActive;
        public synchronized void execute(final Runnable r) {
            mTasks.offer(new Runnable() {
                public void run() {
                    try {
                        r.run();
                    } finally {
                        scheduleNext();
                    }
                }
            });
            if (mActive == null) {
                scheduleNext();
            }
        }
        protected synchronized void scheduleNext() {
            if ((mActive = mTasks.poll()) != null) {
                THREAD_POOL_EXECUTOR.execute(mActive);
            }
        }
    }
/*
4月16日
异步任务AsyncTask
AsyncTask内部定义了一个Handler对象
*/

 private static class InternalHandler extends Handler {
        public InternalHandler() {
            super(Looper.getMainLooper());
        }
        @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
        @Override
        public void handleMessage(Message msg) {
            AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
            switch (msg.what) {
                case MESSAGE_POST_RESULT:
                    // There is only one result
                    result.mTask.finish(result.mData[0]);
                    break;
                case MESSAGE_POST_PROGRESS:
                    result.mTask.onProgressUpdate(result.mData);
                    break;
            }
        }
    }
/*
4月17日
异步任务AsyncTask
异步任务完成的消息会调用finish方法
*/

private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }
/*
4月18日
HandlerThread
HandlerThread的基本用法
*/

/**
 * 测试HandlerThread的基本使用
 */
HandlerThread mHandlerThread = new HandlerThread("myHandlerThreand");
        mHandlerThread.start();


        // 创建的Handler将会在mHandlerThread线程中执行
        final Handler mHandler = new Handler(mHandlerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                Log.i("tag", "接收到消息:" + msg.obj.toString());
            }
        };
        title = (TextView) findViewById(R.id.title);
        title.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Message msg = new Message();
                msg.obj = "11111";
                mHandler.sendMessage(msg);
                msg = new Message();
                msg.obj = "2222";
                mHandler.sendMessage(msg);
            }
        });
/*
4月19日
HandlerThread
Thread的run方法
*/

@Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }
/*
4月20日
IntentService
自身含有消息循环的Service
定义一个IntentService
*/

/**
 * 自定义IntentService
 */
public class MIntentService extends IntentService{
    public MIntentService() {
        super("");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        Log.i("tag", intent.getStringExtra("params") + "  " + Thread.currentThread().getId());
    }
}
/*
4月21日
IntentService
自身含有消息循环的Service
启动service
*/

/**
 * 定义TextView点击事件,启动IntentService服务
 */
title.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, MIntentService.class);
                intent.putExtra("params", "ceshi");
                startService(intent);
            }
        });
点击title组件的时候,service接收到了消息并打印出了传递过去的intent参数,同时显示onHandlerIntent方法执行的线程ID并非主线程
/*
4月22日
IntentService
自身含有消息循环的Service
service源码
*/

public abstract class IntentService extends Service {
    private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;
    private String mName;
    private boolean mRedelivery;
    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }
        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }
    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     * @param name Used to name the worker thread, important only for debugging.
     */
    public IntentService(String name) {
        super();
        mName = name;
    }
    @Override
    public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }
    @Override
    public void onStart(Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }
@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
     @WorkerThread
    protected abstract void onHandleIntent(Intent intent);
}
/*
4月23日
IntentService
自身含有消息循环的Service
消息队列的处理逻辑
*/

private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }
        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }
/*
4月24日
SystemServer进程启动流程
SystemServer.run方法的实现
*/

private void run() {
        ...
        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        }


        ...
        if (!SystemProperties.get("persist.sys.language").isEmpty()) {
            final String languageTag = Locale.getDefault().toLanguageTag();


            SystemProperties.set("persist.sys.locale", languageTag);
            SystemProperties.set("persist.sys.language", "");
            SystemProperties.set("persist.sys.country", "");
            SystemProperties.set("persist.sys.localevar", "");
        }
        // Here we go!
        Slog.i(TAG, "Entered the Android system server!");
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis())
        ...
        SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
        // Enable the sampling profiler.
        if (SamplingProfilerIntegration.isEnabled()) {
            SamplingProfilerIntegration.start();
            mProfilerSnapshotTimer = new Timer();
            mProfilerSnapshotTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    SamplingProfilerIntegration.writeSnapshot("system_server", null);
                }
            }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
        }
/*
4月25日
SystemServer进程启动流程
SystemServer.run方法的实现
*/

 VMRuntime.getRuntime().clearGrowthLimit();
        // The system server has to run all of the time, so it needs to be
        // as efficient as possible with its memory usage.
        VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
        // Some devices rely on runtime fingerprint generation, so make sure
        // we've defined it before booting further.
        Build.ensureFingerprintProperty();
        // Within the system server, it is an error to access Environment paths without
        // explicitly specifying a user.
        Environment.setUserRequired(true);
        // Ensure binder calls into the system always run at foreground priority.
        BinderInternal.disableBackgroundScheduling(true);
        // Prepare the main looper thread (this thread).
        android.os.Process.setThreadPriority(
                android.os.Process.THREAD_PRIORITY_FOREGROUND);
        android.os.Process.setCanSelfBackground(false);
        Looper.prepareMainLooper();
        // Initialize native services.
        System.loadLibrary("android_servers");
        // Check whether we failed to shut down last time we tried.
        // This call may not return.
        performPendingShutdown();
        // Initialize the system context.
        createSystemContext();
        // Create the system service manager.
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        // Start services.
        try {
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        }
        // For debug builds, log event loop stalls to dropbox for analysis.
        if (StrictMode.conditionallyEnableDebugLogging()) {
            Slog.i(TAG, "Enabled StrictMode for system server main thread.");
        }
        // Loop forever.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
/*
4月26日
SystemServer进程启动流程
startBootstrapServices() 主要用于启动系统Boot级服务
startBootstrapServices方法
*/

private void startBootstrapServices() {
        Installer installer = mSystemServiceManager.startService(Installer.class);
        // Activity manager runs the show.
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
        // Now that the power manager has been started, let the activity manager
        // initialize power management features.
        mActivityManagerService.initPowerManagement();
        // Manages LEDs and display backlight so we need it to bring up the display.
        mSystemServiceManager.startService(LightsService.class);
        // Display manager is needed to provide display metrics before package manager
        // starts up.
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
        // We need the default display before we can initialize the package manager.
        mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
        // Only run "core" apps if we're encrypting the device.
        String cryptState = SystemProperties.get("vold.decrypt");
        if (ENCRYPTING_STATE.equals(cryptState)) {
            Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
            mOnlyCore = true;
        } else if (ENCRYPTED_STATE.equals(cryptState)) {
            Slog.w(TAG, "Device encrypted - only parsing core apps");
            mOnlyCore = true;

        }

/*
4月27日
SystemServer进程启动流程
startBootstrapServices() 主要用于启动系统Boot级服务
startBootstrapServices方法
*/

        // Start the package manager.
        Slog.i(TAG, "Package Manager");
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        mFirstBoot = mPackageManagerService.isFirstBoot();
        mPackageManager = mSystemContext.getPackageManager();
        Slog.i(TAG, "User Service");
        ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());
        // Initialize attribute cache used to cache resources from packages.
        AttributeCache.init(mSystemContext);
        // Set up the Application instance for the system process and get started.
        mActivityManagerService.setSystemProcess();
        // The sensor service needs access to package manager service, app ops
        // service, and permissions service, therefore we start it after them.
        startSensorService();
    }
/*
4月28日
SystemServer进程启动流程
startCoreServices() 主要用于启动系统核心的服务
startService方法的具体实现
*/

public <T extends SystemService> T startService(Class<T> serviceClass) {
        final String name = serviceClass.getName();
        Slog.i(TAG, "Starting " + name);
        // Create the service.
        if (!SystemService.class.isAssignableFrom(serviceClass)) {
            throw new RuntimeException("Failed to create " + name
                    + ": service must extend " + SystemService.class.getName());
        }
        final T service;
        try {
            Constructor<T> constructor = serviceClass.getConstructor(Context.class);
            service = constructor.newInstance(mContext);
        } catch (InstantiationException ex) {
            throw new RuntimeException("Failed to create service " + name
                    + ": service could not be instantiated", ex);
        } catch (IllegalAccessException ex) {
            throw new RuntimeException("Failed to create service " + name
                    + ": service must have a public constructor with a Context argument", ex);
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException("Failed to create service " + name
                    + ": service must have a public constructor with a Context argument", ex);
        } catch (InvocationTargetException ex) {
            throw new RuntimeException("Failed to create service " + name
                    + ": service constructor threw an exception", ex);
        }
        // Register it.
        mServices.add(service);
        // Start it.
        try {
            service.onStart();
        } catch (RuntimeException ex) {
            throw new RuntimeException("Failed to start service " + name
                    + ": onStart threw an exception", ex);
        }
        return service;
    }
//通过反射器构造方法创建出服务类,然后添加到SystemServiceManager的服务列表数据中,最后调用了service.onStart()方法
/*
4月29日
SystemServer进程启动流程
Lifecycle类的定义
*/

public static final class Lifecycle extends SystemService {
        private final ActivityManagerService mService;
        public Lifecycle(Context context) {
            super(context);
            mService = new ActivityManagerService(context);
        }
        @Override
        public void onStart() {
            mService.start();
        }
        public ActivityManagerService getService() {
            return mService;
        }
    }
/*
4月30日
SystemServer进程启动流程
ActivityManagerService的start方法的实现
*/

private void start() {
        Process.removeAllProcessGroups();
        mProcessCpuThread.start()
        mBatteryStatsService.publish(mContext);
        mAppOpsService.publish(mContext);
        Slog.d("AppOps", "AppOpsService published");
        LocalServices.addService(ActivityManagerInternal.class, new LocalService());
    }
/*
5月1日
SystemServer进程启动流程
startCoreServices方法
*/

private void startCoreServices() {
        // Tracks the battery level.  Requires LightService.
        mSystemServiceManager.startService(BatteryService.class);
        // Tracks application usage stats.
        mSystemServiceManager.startService(UsageStatsService.class);
        mActivityManagerService.setUsageStatsManager(
                LocalServices.getService(UsageStatsManagerInternal.class));
        // Update after UsageStatsService is available, needed before performBootDexOpt.
        mPackageManagerService.getUsageStatsIfNoPackageUsageInfo()
        // Tracks whether the updatable WebView is in a ready state and watches for update installs.
        mSystemServiceManager.startService(WebViewUpdateService.class);
    }
/*
5月3日
断点续传-音乐播放器
主框架

*/

            public class MainActivity extends ListActivity  {

            // 固定下载的资源路径,这里可以设置网络上的地址
      private static final String URL = "http://10.81.36.193:8080/";
      // 固定存放下载的音乐的路径:SD卡目录下
      private static final String SD_PATH = "/mnt/sdcard/";
      // 存放各个下载器
      private Map<String, Downloader> downloaders = new HashMap<String, Downloader>();
      // 存放与下载器对应的进度条
      private Map<String, ProgressBar> ProgressBars = new HashMap<String, ProgressBar>();
      /**
       * 利用消息处理机制适时更新进度条
       */
      private Handler mHandler = new Handler() {
          public void handleMessage(Message msg) {
              if (msg.what == 1) {
                  String url = (String) msg.obj;
                  int length = msg.arg1;
                  ProgressBar bar = ProgressBars.get(url);
                  if (bar != null) {
                      // 设置进度条按读取的length长度更新
                      bar.incrementProgressBy(length);
                      if (bar.getProgress() == bar.getMax()) {
                          Toast.makeText(MainActivity.this, "下载完成!", 0).show();
                          // 下载完成后清除进度条并将map中的数据清空
/*
5月4日
断点续传-音乐播放器
主框架
*/

LinearLayout layout = (LinearLayout) bar.getParent();
                          layout.removeView(bar);
                          ProgressBars.remove(url);
                          downloaders.get(url).delete(url);
                          downloaders.get(url).reset();
                          downloaders.remove(url);
                      }
                  }
              }
          }
      };
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          showListView();
          StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());
        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().penaltyDeath().build());
      }
/*
5月5日
断点续传-音乐播放器
主框架
*/

// 显示listView,这里可以随便添加音乐
      private void showListView() {
          List<Map<String, String>> data = new ArrayList<Map<String, String>>();
          Map<String, String> map = new HashMap<String, String>();
          map.put("name", "mm.mp3");
          data.add(map);
          map = new HashMap<String, String>();
          map.put("name", "pp.mp3");
          data.add(map);
          map = new HashMap<String, String>();
          map.put("name", "tt.mp3");
          data.add(map);
          map = new HashMap<String, String>();
          map.put("name", "ou.mp3");
          data.add(map);
          SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.list_item, new String[] { "name" },
                  new int[] { R.id.tv_resouce_name });
          setListAdapter(adapter);
      }
      /**
       * 响应开始下载按钮的点击事件
       */
      public void startDownload(View v) {
          // 得到textView的内容
          LinearLayout layout = (LinearLayout) v.getParent();
          String musicName = ((TextView) layout.findViewById(R.id.tv_resouce_name)).getText().toString();
          String urlstr = URL + musicName;
          String localfile = SD_PATH + musicName;
/*
5月6日
断点续传-音乐播放器
主框架
*/

 public void startDownload(View v) {
          // 得到textView的内容
          LinearLayout layout = (LinearLayout) v.getParent();
          String musicName = ((TextView) layout.findViewById(R.id.tv_resouce_name)).getText().toString();
          String urlstr = URL + musicName;
          String localfile = SD_PATH + musicName;
          //设置下载线程数为4,这里是我为了方便随便固定的
          int threadcount = 4;
          // 初始化一个downloader下载器
          Downloader downloader = downloaders.get(urlstr);
          if (downloader == null) {
              downloader = new Downloader(urlstr, localfile, threadcount, this, mHandler);
              downloaders.put(urlstr, downloader);
          }
          if (downloader.isdownloading())
             return;
         // 得到下载信息类的个数组成集合
         LoadInfo loadInfo = downloader.getDownloaderInfors();
         // 显示进度条
         showProgress(loadInfo, urlstr, v);
         // 调用方法开始下载
         downloader.download();
     }
/*
5月7日
断点续传-音乐播放器
主框架
*/

/**
      * 显示进度条
      */
     private void showProgress(LoadInfo loadInfo, String url, View v) {
         ProgressBar bar = ProgressBars.get(url);
         if (bar == null) {
             bar = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal);
             bar.setMax(loadInfo.getFileSize());
             bar.setProgress(loadInfo.getComplete());
             ProgressBars.put(url, bar);
             LinearLayout.LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT, 5);
             ((LinearLayout) ((LinearLayout) v.getParent()).getParent()).addView(bar, params);
         }
     }
     /**
      * 响应暂停下载按钮的点击事件
      */
     public void pauseDownload(View v) {
         LinearLayout layout = (LinearLayout) v.getParent();
         String musicName = ((TextView) layout.findViewById(R.id.tv_resouce_name)).getText().toString();
         String urlstr = URL + musicName;
         downloaders.get(urlstr).pause();
     }
}
/*
5月8日
断点续传-音乐播放器
DownloadInfo
*/

package com.example.downloaderstopsart;
public class DownloadInfo {
    private int threadId;// 下载器id
    private int startPos;// 开始点
    private int endPos;// 结束点
    private int compeleteSize;// 完成度
    private String url;// 下载器网络标识
    public DownloadInfo(int threadId, int startPos, int endPos,
            int compeleteSize, String url) {
        this.threadId = threadId;
        this.startPos = startPos;
        this.endPos = endPos;
        this.compeleteSize = compeleteSize;
        this.url = url;
    }
    public DownloadInfo() {
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public int getThreadId() {
        return threadId;
    }
    public void setThreadId(int threadId) {
        this.threadId = threadId;
    }
    public int getStartPos() {
        return startPos;
    }
    public void setStartPos(int startPos) {
        this.startPos = startPos;
    }
    public int getEndPos() {
        return endPos;
    }
    public void setEndPos(int endPos) {
        this.endPos = endPos;
    }
    public int getCompeleteSize() {
        return compeleteSize;
    }
    public void setCompeleteSize(int compeleteSize) {
        this.compeleteSize = compeleteSize;
    }
    public String toString() {
        return "DownloadInfo [threadId=" + threadId + ", startPos=" + startPos
                + ", endPos=" + endPos + ", compeleteSize=" + compeleteSize
                + "]";
    }
}
/*
5月9日
断点续传-音乐播放器
LoadInfo
*/

package com.example.downloaderstopsart;
public class LoadInfo {
    public int fileSize;// 文件大小
    private int complete;// 完成度
    private String urlstring;// 下载器标识
    public LoadInfo(int fileSize, int complete, String urlstring) {
        this.fileSize = fileSize;
        this.complete = complete;
        this.urlstring = urlstring;
    }
    public LoadInfo() {
    }
    public int getFileSize() {
        return fileSize;
    }
    public void setFileSize(int fileSize) {
        this.fileSize = fileSize;
    }
    public int getComplete() {
        return complete;
    }
    public void setComplete(int complete) {
        this.complete = complete;
    }
    public String getUrlstring() {
        return urlstring;
    }
    public void setUrlstring(String urlstring) {
        this.urlstring = urlstring;
    }
    @Override
    public String toString() {
        return "LoadInfo [fileSize=" + fileSize + ", complete=" + complete
                + ", urlstring=" + urlstring + "]";
    }
}
/*
5月11日
Android 视频播放器
进度条的界面
*/

<SeekBar
    android:id="@+id/play_seek"
    android:layout_width="match_parent"
    android:layout_height="5dp"
    android:layout_marginLeft="-20dp"
    android:layout_marginRight="-20dp"
    android:indeterminate="false"
    android:max="100"
    android:progress="20"
    android:progressDrawable="@drawable/seekbar_style2"
    android:thumb="@null" />
/*
5月12日
Android 视频播放器
进度条的背景
*/

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@android:id/background">
        <shape>
            <solid android:color="#707070" />
            <size android:height="5dp" />
        </shape>
    </item>
    <item android:id="@android:id/progress">
        <clip>
            <shape>
                <solid android:color="#994310" />
                <size android:height="5dp" />
            </shape>
        </clip>
    </item>
</layer-list>
/*
5月13日
Android 视频播放器
播放与暂停
*/

private Handler UIHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        if (msg.what == UPDATE_UI) {
            // 获取视频当前播放时间
            int currentPosition = videoView.getCurrentPosition();
            // 获取视频播放总时间
            int totalduration = videoView.getDuration();
            // 格式化视频播放时间
            updateTextViewWithTimeFormat(time_current_tv, currentPosition);
            updateTextViewWithTimeFormat(time_total_tv, totalduration);
            play_seek.setMax(totalduration);
            play_seek.setProgress(currentPosition);
            UIHandler.sendEmptyMessageDelayed(UPDATE_UI, 500);
        }
    }
};
/*
5月14日
Android 视频播放器
播放与暂停
*/

play_controller_img.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (videoView.isPlaying()) {
            play_controller_img.setImageResource(R.drawable.play_btn_selector);
            videoView.pause();
            UIHandler.removeMessages(UPDATE_UI);
        } else {
            play_controller_img.setImageResource(R.drawable.pause_btn_selector);
            videoView.start();
            UIHandler.sendEmptyMessage(UPDATE_UI);
        }
    }
});
/*
5月14日
Android 视频播放器
视频进度条
*/

play_seek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        updateTextViewWithTimeFormat(time_current_tv, progress);
    }
    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
        UIHandler.removeMessages(UPDATE_UI);
    }
    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        int progress = seekBar.getProgress();
        // 视频播放进度拖至滚动条位置
        videoView.seekTo(progress);
        UIHandler.sendEmptyMessage(UPDATE_UI);
    }
});
/*
5月15日
Android 视频播放器
音量进度条
*/

// 获取音频服务
mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
/**
 * 获取设备最大音量
 */
int streamMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
/**
 * 获取当前设备音量
 */
int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
volume_seek.setMax(streamMaxVolume);
volume_seek.setProgress(streamVolume);
/*
5月16日
Android 视频播放器
绑定进度条的拖动事件
*/

volume_seek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        /**
         * 设置当前音量
         */
        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, progress, 0);
    }
    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
    }
    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
    }
});
/*
5月17日
Android 视频播放器
转动屏幕的切换
*/

public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    /**
     * 屏幕为横屏
     */
    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
        setVideoViewScale(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        volume_img.setVisibility(View.VISIBLE);
        volume_seek.setVisibility(View.VISIBLE);
        isFullScreen = true;
    }
    /**
     * 屏幕为竖屏
     */
    else {
        setVideoViewScale(ViewGroup.LayoutParams.MATCH_PARENT, DisplayUtil.dip2px(this, 240));
        volume_img.setVisibility(View.GONE);
        volume_seek.setVisibility(View.GONE);
        isFullScreen = false;
    }
}
/*
5月18日
Android 视频播放器
设置屏幕亮度
*/

/**
     * 设置屏幕亮度
     */
    private void setBrightness(Activity activity, float percent) {
        if (activity == null) {
            return;
        }
        if (percent < 0.01f) {
            percent = 0.01f;
        } else if (percent > 1.0f) {
            percent = 1.0f;
        }
        WindowManager.LayoutParams params = activity.getWindow().getAttributes();
        params.screenBrightness = percent;
        activity.getWindow().setAttributes(params);
    }
/*
5月19日
Android 视频播放器
获得当前屏幕亮度
*/

 /**
     * 获得当前屏幕亮度
     *
     * @param activity
     * @return
     */
    private float getBrightnessPercent(Activity activity) {
        WindowManager.LayoutParams params = activity.getWindow().getAttributes();
        return params.screenBrightness;
    }
    private Runnable mSwitchTitleRunnable = new Runnable() {
        @Override
        public void run() {
            gestureOperationHelper.SingleTap();
        }
    };
/*
5月20日
Android 视频播放器
获得当前屏幕亮度
*/

private void initSensor() {
        //初始化重力感应器,func:重力感应屏幕切换
        sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        //获得重力传感器
        sensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        listener = new OrientationSensorListener(mHandler);
        sm.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_UI);
        sm2 = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        sensor2 = sm2.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        listener2 = new OrientationSensorListener2();
        sm2.registerListener(listener2, sensor2, SensorManager.SENSOR_DELAY_UI);
    }
/*
5月21日
Android 视频播放器
 全屏 或者 退出全屏 播放
*/

/**
         * 全屏 或者 退出全屏 播放
         */
        iv_full.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i("HHHH", "切换横屏)))" + stretch_flag);
                //  stretch_flag = sp1.getBoolean("stretch_flag", true);
                if (stretch_flag) {
                    //切换成横屏
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    stretch_flag = false;
                } else {
                    //切换成竖屏
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                    stretch_flag = true;
                }
/*
5月21日
Android 视频播放器
播放器状态
*/

public void onClick(View v) {
        switch (v.getId()) {
            case R.id.imageView_main_play:
                if (iv_suolue != null && iv_suolue.getVisibility() == View.VISIBLE) {
                    iv_suolue.setVisibility(View.GONE);
                }
                Log.i(TAG, "imageView_main_play::播放" + imageView_main_show.isSelected());
                //  if (mediaPlayer != null  && imageView_main_show.isSelected()&& mediaPlayer.isPlaying()) {
                //说明此时正在播放,播放按钮处于播放状态
                try {
                    if (mediaPlayer != null && imageView_main_show.isSelected() && mediaPlayer.isPlaying()) {
                        mediaPlayer.pause();
                        //此时控制条的播放组件应该是显示暂停状态
                        if (iv_play != null) {
                            iv_play.setSelected(false);
                            // iv_play.setImageResource(R.drawable.fvl_selector_play);
                        }
                        imageView_main_show.setSelected(false);
                    } else if (mediaPlayer != null && !imageView_main_show.isSelected()) {
                        imageView_main_show.setSelected(true);
                        mediaPlayer.start();
                        //此时控制条的播放组件应该是显示播放状态
                        if (iv_play != null) {
                            iv_play.setSelected(true);
                        }
                        imageView_main_show.setVisibility(View.GONE);
                    }
/*
5月22日
Android 视频播放器
视频大小
*/

public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Activity activity = weakReference.get();
            if (activity != null) {
                switch (msg.what) {
                    case MEASURE_VIDEO_SIZE:
                        /**
                         * 测量的视频大小
                         */
                        /**
                         * 设置播放大小,如果视频的大小>显示器  设置显示器  反之 视频,取小的设置比率
                         */
                        videoWidth = mediaPlayer.getVideoWidth();
                        Log.i(TAG, "视频的宽度:" + videoWidth);
                        Log.i(TAG, "视频的宽度:::" + screenWidth);
                        videoHeight = mediaPlayer.getVideoHeight();
                        Log.i(TAG, "视频的高度:" + videoHeight);
                        Log.i(TAG, "视频的高度:::" + screenHeight);
                        // screenHeight = display.getHeight();
                        if (videoWidth > display.getWidth() || videoHeight > screenHeight) {
                            //视频的大小>显示器的大小
                            float heightRatio = (float) videoHeight / (float) screenHeight;//高度比率
                            float widthRatio = (float) videoWidth / (float) screenWidth;//宽度比率
                            if (heightRatio > widthRatio) {
                                videoHeight = (int) Math.ceil((float) videoHeight / heightRatio);
                                videoWidth = (int) Math.ceil((float) videoWidth / heightRatio);
                            } else {
                                videoHeight = (int) Math.ceil((float) videoHeight / widthRatio);
                                videoWidth = (int) Math.ceil((float) videoWidth / widthRatio);
                            }
                        }
/*
5月23日
Android 视频播放器
切换屏幕
*/

int orientation = msg.arg1;
                        if (orientation > 45 && orientation < 135) {
                        } else if (orientation > 135 && orientation < 225) {
                        } else if (orientation > 225 && orientation < 315) {
                            Log.i(TAG, "切换成横屏");
                            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                            sennorFlag = false;
                            stretch_flag = false;
                        } else if ((orientation > 315 && orientation < 360) || (orientation > 0 && orientation < 45)) 
                            Log.i(TAG, "切换成竖屏");
                            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                            sennorFlag = true;
                            stretch_flag = true;
                        }
                        break;
/*
5月24日
Android 视频播放器
当出现关于播放媒体的特定信息或者需要发出警告的时候,将调用onInfo
*/

 public boolean onInfo(MediaPlayer mp, int what, int extra) {
        Log.i(TAG, "onInfo:");
        if (what == MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING) {
            //当文件中的音频和视频数据不正确的交错的时候会触发
            Log.i(TAG, "onInfo:MEDIA_INFO_BAD_INTERLEAVING:" + extra);
        } else if (what == MediaPlayer.MEDIA_INFO_NOT_SEEKABLE) {
            //当媒体不能正确的定位
            Log.i(TAG, "onInfo:MEDIA_INFO_NOT_SEEKABLE:" + extra);
        } else if (what == MediaPlayer.MEDIA_INFO_UNKNOWN) {
            //媒体信息尚未指定或者未知
            Log.i(TAG, "onInfo:MEDIA_INFO_UNKNOWN:" + extra);
        } else if (what == MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING) {
            //无法播放视频或者音频太复杂或者码率过高
            Log.i(TAG, "onInfo:MEDIA_INFO_VIDEO_TRACK_LAGGING:" + extra);
        } else if (what == MediaPlayer.MEDIA_INFO_METADATA_UPDATE) {
            //当新的元数据可用时
            Log.i(TAG, "onInfo:MEDIA_INFO_METADATA_UPDATE:" + extra);
        }
        return false;
    }
    @Override
    public void onPrepared(MediaPlayer mp) {
        try {
             /*当不是全屏的时候才需要测量,才需要比较*/
            if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
                //因为配置文件中并未设置横竖屏
                mHandler.sendEmptyMessageDelayed(MEASURE_VIDEO_SIZE, 1000);
            } else if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
                mHandler.sendEmptyMessageDelayed(MEASURE_VIDEO_SIZE, 1000);

            } else

RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);

                surfaceView.setLayoutParams(params);
            }
            //Log.i("屏幕方向:::", isLandScape + "");
/*
5月25日
Android 视频播放器
重力感应监听
*/

 public class OrientationSensorListener implements SensorEventListener {
        private static final int _DATA_X = 0;
        private static final int _DATA_Y = 1;
        private static final int _DATA_Z = 2;
        public static final int ORIENTATION_UNKNOWN = -1;
        private MyHandler myHandler;
        private boolean isSupportGravity = false;
        public OrientationSensorListener(MyHandler myHandler) {
            this.myHandler = myHandler;
        }
        public void onAccuracyChanged(Sensor arg0, int arg1) {
            // TODO Auto-generated method stub
        }
        public void onSensorChanged(SensorEvent event) {
            /**
             * 检测手机自动旋转屏幕的功能是否打开
             */
            isSupportGravity = isscreenAutoRotate()
            if (!isSupportGravity) {
                return;
            }
            if (sennorFlag != stretch_flag)  //只有两个不相同才开始监听行为
            {
                float[] values = event.values;
                int orientation = ORIENTATION_UNKNOWN;
                float X = -values[_DATA_X];
                float Y = -values[_DATA_Y];
                float Z = -values[_DATA_Z];
                float magnitude = X * X + Y * Y;
                // Don't trust the angle if the magnitude is small compared to the y value
                if (magnitude * 4 >= Z * Z) {
                    //屏幕旋转时
                    float OneEightyOverPi = 57.29577957855f;
                    float angle = (float) Math.atan2(-Y, X) * OneEightyOverPi;
                    orientation = 90 - (int) Math.round(angle);
                    // normalize to 0 - 359 range
                    while (orientation >= 360) {
                        orientation -= 360;
                    }
                    while (orientation < 0) {
                        orientation += 360;
                    }
                }
                if (myHandler != null) {
                    myHandler.obtainMessage(10001, orientation, 0).sendToTarget();
                }
            }
        }
    }

/*
5月26日
Android 视频播放器
重力感应监听
*/

    public class OrientationSensorListener2 implements SensorEventListener {
        //初始化重力感应器的坐标轴
        private static final int sensor_X = 0;
        private static final int sensor_Y = 1;
        private static final int sensor_Z = 2;
        private static final int ORIENTATION_UNKNOW = -1;
        private boolean isSupportGravity = false;
        public OrientationSensorListener2() {
        }
        @Override
        public void onSensorChanged(SensorEvent event) {
            /**
             * 检测手机自动旋转屏幕的功能是否打开
             */
            isSupportGravity = isscreenAutoRotate();
            if (!isSupportGravity) {
                return;
            }
            float[] values = event.values;
            int orientation = ORIENTATION_UNKNOW;
            float X = -values[sensor_X];
            float Y = -values[sensor_Y];

            float Z = -values[sensor_Z];

/*
5月27日
Android 视频播放器
重力感应监听
*/

            /**
             * 重力传感器监听手机的摆放状态的算法
             */
            float magnitude = X * X + Y * Y;
            // Don't trust the angle if the magnitude is small compared to the y value
            if (magnitude * 4 >= Z * Z) {
                //屏幕旋转时
                float OneEightyOverPi = 57.29577957855f;
                float angle = (float) Math.atan2(-Y, X) * OneEightyOverPi;
                orientation = 90 - (int) Math.round(angle);
                // normalize to 0 - 359 range
                while (orientation >= 360) {
                    orientation -= 360;
                }
                while (orientation < 0) {
                    orientation += 360;
                }
            }
            if (orientation > 225 && orientation < 315) {  //横屏
                sennorFlag = false;
            } else if ((orientation > 315 && orientation < 360) || (orientation > 0 && orientation < 45)) {  //竖屏
                sennorFlag = true;
            }
            if (stretch_flag == sennorFlag) {  //点击变成横屏  屏幕 也转横屏 激活
                Log.i(TAG, "激活");
                sm.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_UI);
            }
        }
        @Override
/*
5月28日
Android 视频播放器
重力感应监听
*/

        public void onAccuracyChanged(Sensor sensor, int accuracy) {
        }
    }
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);


        Log.i("TTTTT", "onConfigurationChanged");
        if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
            //如果是横屏
            Log.i("WWWWWW", "横屏");
            RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
            surfaceView.setLayoutParams(params);

            if (iv_suolue.getVisibility() == View.VISIBLE && !iv_play.isSelected() && !imageView_main_show.isSelected()) {
                iv_suolue.setVisibility(View.GONE);
                new GetVideoBitmapAsyncTask(iv_suolue, surfaceView).execute(filepath);
            }


        } else if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
            mHandler.sendEmptyMessage(MEASURE_VIDEO_SIZE);
            Log.i("*****", "竖屏");
        } else if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
            mHandler.sendEmptyMessage(MEASURE_VIDEO_SIZE);
            Log.i("*****", "无屏");
        }


    }
/*
5月29日
Android 视频播放器
重力感应监听
*/

/**
     * 检测手机自动旋转的是否打开
     *
     * @return
     */

    private boolean isscreenAutoRotate() {
        int gravity = 0;
        try {
            gravity = Settings.System.getInt(getContentResolver(), Settings.System.ACCELEROMETER_ROTATION);
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
            Log.i(TAG, "检测手机是否打开屏幕旋转出错");
        }
        return gravity == 1;
    }
}
/*
5月30日
Android 视频播放器
MainActivity
*/

package com.example.videotest1;
import com.example.service.ServiceTest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity {
    public static SurfaceView sv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sv = (SurfaceView) findViewById(R.id.surfaceView1);// 获得SurfaceView控件
    }
    /*
     *点击那4个按钮后触发的事件
     */
    public void click(View v) {
        Intent intent = new Intent(MainActivity.this, ServiceTest.class);
        int op = -1;// 定义一个中间变量
        switch (v.getId()) {
        case R.id.play:
            op = 1;
            Toast.makeText(MainActivity.this, "视频正在播放...", Toast.LENGTH_SHORT)
                    .show();
            break;
        case R.id.pause:
            op = 2;
            Toast.makeText(MainActivity.this, "视频暂停播放...", Toast.LENGTH_SHORT)
                    .show();
            break;
        case R.id.stop:
            op = 3;
            Toast.makeText(MainActivity.this, "视频停止播放...", Toast.LENGTH_SHORT)
                    .show();
            break;
        case R.id.finish:
            if (intent != null) {
                stopService(intent);
            }
            finish();
            break;
        default:
            break;
        }
        Bundle bundle = new Bundle();// 声明一个Bundle对象并实例化
        bundle.putInt("middle", op);// 把中间变量op放置到middle这个键
        intent.putExtras(bundle);// 用intent把bundle放入进去
        startService(intent);// 开始服务
    }
/*
5月31日
Android 视频播放器
MainActivity
*/

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {


        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}
/*
6月1日
Android 视频播放器
Servic
eTest
*/
package com.example.service;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.IBinder;
public class ServiceTest extends Service {
    public static MediaPlayer player;// 声明MediaPlayer对象
    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }
    // 创建服务
    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        if (player == null) {
            try {
                player = new MediaPlayer();//实例化MediaPlayer对象
                player.setDataSource("/sdcard/wf2.mp4");// 设置要播放的视频
                player.setLooping(false);// 设置视频不循环播放
                super.onCreate();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    // 开始服务
/*
6月2日
Android 视频播放器
ServiceTest
*/

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        Bundle bundle = intent.getExtras();// 获得从MainActivity传来的bundle对象
        int op = bundle.getInt("middle");// 获得从MainActivity.java里传递过来的op
        switch (op) {
        case 1:// 当op为1,即点击了播放按钮
            play();// 调用play()方法
            break;
        case 2:// 当op为2,即点击了暂停按钮
            pause();// 调用pause()方法
            break;
        case 3:// 当op为3,即点击了停止按钮
            stop();// 调用stop()方法
            break;
        default:
            break;
        }
        return super.onStartCommand(intent, flags, startId);
    }
    // 播放视频play()方法
    private void play() {
        // TODO Auto-generated method stub
        if (player != null && !player.isPlaying()) {
            player.setDisplay(com.example.videotest1.MainActivity.sv
                    .getHolder());//把视频画面显示出来
            try {
                player.prepare();//预加载视频
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            player.start();// 开始播放音乐
        }
    }
/*
6月3日
Android 视频播放器
ServiceTest
*/

    private void pause() {
        // TODO Auto-generated method stub
        if (player != null && player.isPlaying()) {
            player.pause();// 暂停视频的播放
        }
    }
    private void stop() {
        // TODO Auto-generated method stub
        if (player != null) {
            player.seekTo(0);//如果点击播放按钮的话会从头播放
            player.stop();// 停止音乐的播放
        }
    }
    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        if (player != null) {
            player.stop();//停止播放视频
            player.release();// 释放资源
            player = null;
        }
        super.onDestroy();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值