Android service解析
1.什么是service
2.Service的启动过程
3.Service的绑定过程
1.什么是service
Service是Android中实现程序后台运行的解决方案,它主要用来处理与用户界面无关的业务逻辑。
Service分为本地服务和远程服务:区分这两种服务就是看客户端和服务端是否在同一个进程中。
本地服务:服务和启动服务的activity在同一个进程中。该服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外本地服务因为是在同一进程因此不需要IPC,也不需要AIDL。相应bindService会方便很多,当主进程被Kill后,服务便会终止。一般使用在音乐播放器播放等不需要常驻的服务。
远程服务:服务和启动服务的activity在不同进程中。由于是独立的进程,因此在Activity所在进程被Kill的时候,该服务依然在运行,不受其他进程影响,有利于为多个进程提供服务具有较高的灵活性。由于是独立的进程,会占用一定资源,并且使用AIDL进行IPC比较麻烦。一般用于系统的Service,这种Service是常驻的。
开启服务也有两种方式,一种是startService(),他对应的结束服务的方法是stopService(),另一种是bindService(),结束服务的是unBindService(),这两种方式的区别就是:当客户端Client使用startService方法开启服务的时候,这个服务和Client之间没有任何联系,Service的运行和Client是相互独立的,想结束这个服务的话,就在服务本身中调用stopService()方法结束服务。而当客户端Client使用bindService方法启动服务的时候,这个服务和Client是一种关联的关系,Client端可以获得服务端的访问接口。要是结束服务的话,需要在Client中和服务断开,调用unBindService方法。
下面针对这两种启动方式进行详细的分析说明。
2.Service的启动过程
整个service的启动时序图如下所示:
//frameworks/base/core/java/android/content/ContextWrapper.java
667 @Override
668 public ComponentName startService(Intent service) {
669 return mBase.startService(service);
670 }
671
mBase的类型是Context,Context的实现类是ContextImpl。它们的继承关系如下:
所以接下来看下ContextImpl的startService()方法。
//frameworks/base/core/java/android/app/ContextImpl.java
1568 @Override
1569 public ComponentName startService(Intent service) {
1570 warnIfCallingFromSystemProcess();
1571 return startServiceCommon(service, false, mUser);
1572 }1596 private ComponentName startServiceCommon(Intent service, boolean requireForeground,
1597 UserHandle user) {
1598 try {
1599 validateServiceIntent(service);
1600 service.prepareToLeaveProcess(this);
1601 ComponentName cn = ActivityManager.getService().startService(
1602 mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
1603 getContentResolver()), requireForeground,
1604 getOpPackageName(), user.getIdentifier());
1605 if (cn != null) {
1606 if (cn.getPackageName().equals("!")) {
1607 throw new SecurityException(
1608 "Not allowed to start service " + service
1609 + " without permission " + cn.getClassName());
1610 } else if (cn.getPackageName().equals("!!")) {
1611 throw new SecurityException(
1612 "Unable to start service " + service
1613 + ": " + cn.getClassName());
1614 } else if (cn.getPackageName().equals("?")) {
1615 throw new IllegalStateException(
1616 "Not allowed to start service " + service + ": " + cn.getClassName());
1617 }
1618 }
1619 return cn;
1620 } catch (RemoteException e) {
1621 throw e.rethrowFromSystemServer();
1622 }
1623 }
ActivityManager.getService()其实就是ActivityManagerService,调用ActivityManagerService类里面的startService方法。
//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
13894 public ComponentName startService(IApplicationThread caller, Intent service,
13895 String resolvedType, boolean requireForeground, String callingPackage, int userId)
13896 throws TransactionTooLargeException {
13897 enforceNotIsolatedCaller("startService");
13898 // Refuse possible leaked file descriptors
13899 if (service != null && service.hasFileDescriptors() == true) {
13900 throw new IllegalArgumentException("File descriptors passed in Intent");
13901 }
13902
13903 if (callingPackage == null) {
13904 throw new IllegalArgumentException("callingPackage cannot be null");
13905 }
13906
13907 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
13908 "*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground);
13909 synchronized(this) {
13910 final int callingPid = Binder.getCallingPid();
13911 final int callingUid = Binder.getCallingUid();
13912 final long origId = Binder.clearCallingIdentity();
13913 ComponentName res;
13914 try {
13915 res = mServices.startServiceLocked(caller, service,
13916 resolvedType, callingPid, callingUid,
13917 requireForeground, callingPackage, userId);
13918 } finally {
13919 Binder.restoreCallingIdentity(origId);
13920 }
13921 return res;
13922 }
13923 }
通过mServices对象调用了startServiceLocked()方法,mServices是ActiveServices类的对象,可以看做是辅助ActivityManagerServices来管理Service的类,我们来看下它的startServiceLocked()方法.
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
401 ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
402 int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
403 throws TransactionTooLargeException {
404 return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired,
405 callingPackage, userId, false);
406 }
407
408 ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
409 int callingPid, int callingUid, boolean fgRequired, String callingPackage,
410 final int userId, boolean allowBackgroundActivityStarts)
411 throws TransactionTooLargeException {
412 if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
413 + " type=" + resolvedType + " args=" + service.getExtras());........
640 ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
641 return cmp;
642 }
在最后,调用了startServiceInnerLocked()方法.
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
689 ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
690 boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {........
701 String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
702 if (error != null) {
703 return new ComponentName("!!", error);
704 }........
在这里会调用一个重要的函数bringUpServiceLocked。
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
500 private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
2501 boolean whileRestarting, boolean permissionsReviewRequired)
2502 throws TransactionTooLargeException {
2503 if (r.app != null && r.app.thread != null) {//这里会调用service.onStartCommand()
2504 sendServiceArgsLocked(r, execInFg, false);
2505 return null;
2506 }.......
2557 if (!isolated) {
2558 app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
2559 if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
2560 + " app=" + app);
2561 if (app != null && app.thread != null) {
2562 try {
2563 app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);//启动服务
2564 realStartServiceLocked(r, app, execInFg);
2565 return null;
2566 } catch (TransactionTooLargeException e) {
2567 throw e;
2568 } catch (RemoteException e) {
2569 Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
2570 }
2571
2572 // If a dead object exception was thrown -- fall through to
2573 // restart the application.
2574 }........//如果进程不存在,首先创建进程
2595 if (app == null && !permissionsReviewRequired) {
2596 if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
2597 hostingRecord, false, isolated, false)) == null) {
2598 String msg = "Unable to launch app "
2599 + r.appInfo.packageName + "/"
2600 + r.appInfo.uid + " for service "
2601 + r.intent.getIntent() + ": process is bad";
2602 Slog.w(TAG, msg);
2603 bringDownServiceLocked(r);
2604 return msg;
2605 }
2606 if (isolated) {
2607 r.isolatedProc = app;
2608 }
2609 }........
2624 if (r.delayedStop) {
2625 // Oh and hey we've already been asked to stop!
2626 r.delayedStop = false;
2627 if (r.startRequested) {
2628 if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
2629 "Applying delayed stop (in bring up): " + r);
2630 stopServiceLocked(r);
2631 }
2632 }
2633
2634 return null;
2635 }
2636
目标进程已存在,则直接执行realStartServiceLocked();若目标进程不存在,则先执行startProcessLocked创建进程, 经过层层调用最后会调用到AMS.attachApplicationLocked, 然后再执行realStartServiceLocked()。
创建进程的过程我们再之前activity启动的时候已经分析过,所以这里我们直接分析realStartServiceLocked。
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
2652 private final void realStartServiceLocked(ServiceRecord r,
2653 ProcessRecord app, boolean execInFg) throws RemoteException {
2654 if (app.thread == null) {
2655 throw new RemoteException();
2656 }........
2669 boolean created = false;
2670 try {
2671 if (LOG_SERVICE_START_STOP) {
2672 String nameTerm;
2673 int lastPeriod = r.shortInstanceName.lastIndexOf('.');
2674 nameTerm = lastPeriod >= 0 ? r.shortInstanceName.substring(lastPeriod)
2675 : r.shortInstanceName;
2676 EventLogTags.writeAmCreateService(
2677 r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
2678 }
2679 StatsLog.write(StatsLog.SERVICE_LAUNCH_REPORTED, r.appInfo.uid, r.name.getPackageName(),
2680 r.name.getClassName());
2681 synchronized (r.stats.getBatteryStats()) {
2682 r.stats.startLaunchedLocked();
2683 }
2684 mAm.notifyPackageUse(r.serviceInfo.packageName,
2685 PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
2686 app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);//binder调用,create service
2687 app.thread.scheduleCreateService(r, r.serviceInfo,
2688 mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
2689 app.getReportedProcState());
2690 r.postNotification();
2691 created = true;
2692 } catch (DeadObjectException e) {
2693 Slog.w(TAG, "Application dead when creating service " + r);
2694 mAm.appDiedLocked(app);
2695 throw e;........//bind service 我们会在下一部分详细介绍
2719 requestServiceBindingsLocked(r, execInFg);........//bind service 我们会在下一部分详细介绍
2735 sendServiceArgsLocked(r, execInFg, true);
2736
2737 if (r.delayed) {
2738 if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r);
2739 getServiceMapLocked(r.userId).mDelayedStartList.remove(r);
2740 r.delayed = false;
2741 }
2742
2743 if (r.delayedStop) {
2744 // Oh and hey we've already been asked to stop!
2745 r.delayedStop = false;
2746 if (r.startRequested) {
2747 if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
2748 "Applying delayed stop (from start): " + r);
2749 stopServiceLocked(r);
2750 }
2751 }
2752 }
//frameworks/base/core/java/android/app/ActivityThread.java
943 public final void scheduleCreateService(IBinder token,
944 ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
945 updateProcessState(processState, false);
946 CreateServiceData s = new CreateServiceData();
947 s.token = token;
948 s.info = info;
949 s.compatInfo = compatInfo;
950
951 sendMessage(H.CREATE_SERVICE, s);
952 }1853 public void handleMessage(Message msg) {
1854 if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
1855 switch (msg.what) {........
1873 case CREATE_SERVICE:
1874 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
1875 handleCreateService((CreateServiceData)msg.obj);
1876 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1877 break;........3923 @UnsupportedAppUsage
3924 private void handleCreateService(CreateServiceData data) {
3925 // If we are getting ready to gc after going to the background, well
3926 // we are back active so skip it.
3927 unscheduleGcIdler();
3928
3929 LoadedApk packageInfo = getPackageInfoNoCheck(
3930 data.info.applicationInfo, data.compatInfo);
3931 Service service = null;
3932 try {////通过反射的方式,调用ClassLoader的loadClass()方法,创建一个Service对象
3933 java.lang.ClassLoader cl = packageInfo.getClassLoader();
3934 service = packageInfo.getAppFactory()
3935 .instantiateService(cl, data.info.name, data.intent);
3936 } catch (Exception e) {
3937 if (!mInstrumentation.onException(service, e)) {
3938 throw new RuntimeException(
3939 "Unable to instantiate service " + data.info.name
3940 + ": " + e.toString(), e);
3941 }
3942 }
3943
3944 try {
3945 if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
3946 //创建ContextImpl对象
3947 ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
3948 context.setOuterContext(service);
3949 //创建Application
3950 Application app = packageInfo.makeApplication(false, mInstrumentation);
3951 service.attach(context, this, data.info.name, data.token, app,
3952 ActivityManager.getService());//调用Service的onCreate()方法
3953 service.onCreate();
3954 mServices.put(data.token, service);
3955 try {
3956 ActivityManager.getService().serviceDoneExecuting(
3957 data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
3958 } catch (RemoteException e) {
3959 throw e.rethrowFromSystemServer();
3960 }
3961 } catch (Exception e) {
3962 if (!mInstrumentation.onException(service, e)) {
3963 throw new RuntimeException(
3964 "Unable to create service " + data.info.name
3965 + ": " + e.toString(), e);
3966 }
3967 }
3968 }
最终调用Service.onCreate()方法,对于目标服务都是继承于Service,并覆写该方式,调用目标服务的onCreate()方法。至此service的启动全部结束。
3.Service的绑定过程
通过bind也可以启动service,service的绑定流程如下:
//frameworks/base/core/java/android/content/ContextWrapper.java
708 @Override
709 public boolean bindService(Intent service, int flags, Executor executor,
710 ServiceConnection conn) {
711 return mBase.bindService(service, flags, executor, conn);
712 }//frameworks/base/core/java/android/app/ContextImpl.java
1647 @Override
1648 public boolean bindService(Intent service, ServiceConnection conn, int flags) {
1649 warnIfCallingFromSystemProcess();
1650 return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null,
1651 getUser());
1652 }1707 private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
1708 String instanceName, Handler handler, Executor executor, UserHandle user) {
1709 // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
1710 IServiceConnection sd;
1711 if (conn == null) {
1712 throw new IllegalArgumentException("connection is null");
1713 }
1714 if (handler != null && executor != null) {
1715 throw new IllegalArgumentException("Handler and Executor both supplied");
1716 }
1717 if (mPackageInfo != null) {
1718 if (executor != null) {
1719 sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
1720 } else {
1721 sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
1722 }
1723 } else {
1724 throw new RuntimeException("Not supported in system context");
1725 }
1726 validateServiceIntent(service);
1727 try {
1728 IBinder token = getActivityToken();
1729 if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
1730 && mPackageInfo.getApplicationInfo().targetSdkVersion
1731 < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
1732 flags |= BIND_WAIVE_PRIORITY;
1733 }
1734 service.prepareToLeaveProcess(this);//AMS binder调用
1735 int res = ActivityManager.getService().bindIsolatedService(
1736 mMainThread.getApplicationThread(), getActivityToken(), service,
1737 service.resolveTypeIfNeeded(getContentResolver()),
1738 sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
1739 if (res < 0) {
1740 throw new SecurityException(
1741 "Not allowed to bind to service " + service);
1742 }
1743 return res != 0;
1744 } catch (RemoteException e) {
1745 throw e.rethrowFromSystemServer();
1746 }
1747 }
调用AMS的函数bindIsolatedService。
//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
14041 public int bindIsolatedService(IApplicationThread caller, IBinder token, Intent service,
14042 String resolvedType, IServiceConnection connection, int flags, String instanceName,
14043 String callingPackage, int userId) throws TransactionTooLargeException {
14044 enforceNotIsolatedCaller("bindService");
14045
14046 // Refuse possible leaked file descriptors
14047 if (service != null && service.hasFileDescriptors() == true) {
14048 throw new IllegalArgumentException("File descriptors passed in Intent");
14049 }
14050
14051 if (callingPackage == null) {
14052 throw new IllegalArgumentException("callingPackage cannot be null");
14053 }
14054
14055 // Ensure that instanceName, which is caller provided, does not contain
14056 // unusual characters.
14057 if (instanceName != null) {
14058 for (int i = 0; i < instanceName.length(); ++i) {
14059 char c = instanceName.charAt(i);
14060 if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
14061 || (c >= '0' && c <= '9') || c == '_' || c == '.')) {
14062 throw new IllegalArgumentException("Illegal instanceName");
14063 }
14064 }
14065 }
14066
14067 synchronized(this) {
14068 return mServices.bindServiceLocked(caller, token, service,
14069 resolvedType, connection, flags, instanceName, callingPackage, userId);
14070 }
14071 }
最后调用ActiveServices的bindServiceLocked函数
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
1548 int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
1549 String resolvedType, final IServiceConnection connection, int flags,
1550 String instanceName, String callingPackage, final int userId)
1551 throws TransactionTooLargeException {
1552 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service
1553 + " type=" + resolvedType + " conn=" + connection.asBinder()
1554 + " flags=0x" + Integer.toHexString(flags));//获取调用者的进程信息
1555 final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);.......//token不为空,代表具有activity
1564 if (token != null) {
1565 activity = mAm.mAtmInternal.getServiceConnectionsHolder(token);
1566 if (activity == null) {
1567 Slog.w(TAG, "Binding with unknown activity: " + token);
1568 return 0;
1569 }
1570 }.......//根据intent检索服务
1625 ServiceLookupResult res =
1626 retrieveServiceLocked(service, instanceName, resolvedType, callingPackage,
1627 Binder.getCallingPid(), Binder.getCallingUid(), userId, true,
1628 callerFg, isBindExternal, allowInstant);........//创建ConnectionRecord 对象
1746 ConnectionRecord c = new ConnectionRecord(b, activity,
1747 connection, flags, clientLabel, clientIntent,
1748 callerApp.uid, callerApp.processName, callingPackage);........
1777 if ((flags&Context.BIND_AUTO_CREATE) != 0) {
1778 s.lastActivity = SystemClock.uptimeMillis();//启动service,和上一节service的启动过程一样
1779 if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
1780 permissionsReviewRequired) != null) {
1781 return 0;
1782 }
1783 }........
1823 } else if (!b.intent.requested) {//回调onBind方法
1824 requestServiceBindingLocked(s, b.intent, callerFg, false);
1825 }
1826
1827 getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s);
1828
1829 } finally {
1830 Binder.restoreCallingIdentity(origId);
1831 }
1832
1833 return 1;
1834 }
可以看到最终也是通过bringUpServiceLocked()启动目标服务,后面目标程序的启动就和上一章一样,区别在于bindService在调用realStartServiceLocked之后继续调用requestServiceBindingsLocked和sendServiceArgsLocked,这两个函数的执行和startService的时候不同。
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
2652 private final void realStartServiceLocked(ServiceRecord r,
2653 ProcessRecord app, boolean execInFg) throws RemoteException {
2654 if (app.thread == null) {
2655 throw new RemoteException();
2656 }........
2669 boolean created = false;
2670 try {
2671 if (LOG_SERVICE_START_STOP) {
2672 String nameTerm;
2673 int lastPeriod = r.shortInstanceName.lastIndexOf('.');
2674 nameTerm = lastPeriod >= 0 ? r.shortInstanceName.substring(lastPeriod)
2675 : r.shortInstanceName;
2676 EventLogTags.writeAmCreateService(
2677 r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
2678 }
2679 StatsLog.write(StatsLog.SERVICE_LAUNCH_REPORTED, r.appInfo.uid, r.name.getPackageName(),
2680 r.name.getClassName());
2681 synchronized (r.stats.getBatteryStats()) {
2682 r.stats.startLaunchedLocked();
2683 }
2684 mAm.notifyPackageUse(r.serviceInfo.packageName,
2685 PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
2686 app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);//binder调用,create service
2687 app.thread.scheduleCreateService(r, r.serviceInfo,
2688 mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
2689 app.getReportedProcState());
2690 r.postNotification();
2691 created = true;
2692 } catch (DeadObjectException e) {
2693 Slog.w(TAG, "Application dead when creating service " + r);
2694 mAm.appDiedLocked(app);
2695 throw e;........//bind service 详情见下
2719 requestServiceBindingsLocked(r, execInFg);........//bind service 详情见下
2735 sendServiceArgsLocked(r, execInFg, true);
2736
2737 if (r.delayed) {
2738 if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r);
2739 getServiceMapLocked(r.userId).mDelayedStartList.remove(r);
2740 r.delayed = false;
2741 }
2742
2743 if (r.delayedStop) {
2744 // Oh and hey we've already been asked to stop!
2745 r.delayedStop = false;
2746 if (r.startRequested) {
2747 if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
2748 "Applying delayed stop (from start): " + r);
2749 stopServiceLocked(r);
2750 }
2751 }
2752 }
我们来详细看下这两个函数的执行过程。
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
2637 private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
2638 throws TransactionTooLargeException {
2639 for (int i=r.bindings.size()-1; i>=0; i--) {
2640 IntentBindRecord ibr = r.bindings.valueAt(i);
2641 if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
2642 break;
2643 }
2644 }
2645 }2285 private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
2286 boolean execInFg, boolean rebind) throws TransactionTooLargeException {
2287 if (r.app == null || r.app.thread == null) {
2288 // If service is not currently running, can't yet bind.
2289 return false;
2290 }
2291 if (DEBUG_SERVICE) Slog.d(TAG_SERVICE, "requestBind " + i + ": requested=" + i.requested
2292 + " rebind=" + rebind);
2293 if ((!i.requested || rebind) && i.apps.size() > 0) {//startService不会进入这个执行流程
2294 try {//发送bind开始的消息
2295 bumpServiceExecutingLocked(r, execInFg, "bind");
2296 r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);//Binder调用,执行ActivityThread里面的scheduleBindService
2297 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
2298 r.app.getReportedProcState());
2299 if (!rebind) {
2300 i.requested = true;
2301 }
2302 i.hasBound = true;
2303 i.doRebind = false;
2304 } catch (TransactionTooLargeException e) {
2305 // Keep the executeNesting count accurate.
2306 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r, e);
2307 final boolean inDestroying = mDestroyingServices.contains(r);
2308 serviceDoneExecutingLocked(r, inDestroying, inDestroying);
2309 throw e;
2310 } catch (RemoteException e) {
2311 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r);
2312 // Keep the executeNesting count accurate.
2313 final boolean inDestroying = mDestroyingServices.contains(r);
2314 serviceDoneExecutingLocked(r, inDestroying, inDestroying);
2315 return false;
2316 }
2317 }
2318 return true;
2319 }
接下来通过binder调用进入ActivityThread。
//frameworks/base/core/java/android/app/ActivityThread.java
954 public final void scheduleBindService(IBinder token, Intent intent,
955 boolean rebind, int processState) {
956 updateProcessState(processState, false);
957 BindServiceData s = new BindServiceData();
958 s.token = token;
959 s.intent = intent;
960 s.rebind = rebind;
961
962 if (DEBUG_SERVICE)
963 Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
964 + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
965 sendMessage(H.BIND_SERVICE, s);
966 }1853 public void handleMessage(Message msg) {
1854 if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));...........
1878 case BIND_SERVICE:
1879 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
1880 handleBindService((BindServiceData)msg.obj);
1881 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1882 break;.......3970 private void handleBindService(BindServiceData data) {
3971 Service s = mServices.get(data.token);
3972 if (DEBUG_SERVICE)
3973 Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
3974 if (s != null) {
3975 try {
3976 data.intent.setExtrasClassLoader(s.getClassLoader());
3977 data.intent.prepareToEnterProcess();
3978 try {
3979 if (!data.rebind) {//执行Service.onBind()回调方法
3980 IBinder binder = s.onBind(data.intent);//调用AMS的publishService
3981 ActivityManager.getService().publishService(
3982 data.token, data.intent, binder);
3983 } else {
3984 s.onRebind(data.intent);
3985 ActivityManager.getService().serviceDoneExecuting(
3986 data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
3987 }
3988 } catch (RemoteException ex) {
3989 throw ex.rethrowFromSystemServer();
3990 }
3991 } catch (Exception e) {
3992 if (!mInstrumentation.onException(s, e)) {
3993 throw new RuntimeException(
3994 "Unable to bind to service " + s
3995 + " with " + data.intent + ": " + e.toString(), e);
3996 }
3997 }
3998 }
3999 }
//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
14085 public void publishService(IBinder token, Intent intent, IBinder service) {
14086 // Refuse possible leaked file descriptors
14087 if (intent != null && intent.hasFileDescriptors() == true) {
14088 throw new IllegalArgumentException("File descriptors passed in Intent");
14089 }
14090
14091 synchronized(this) {
14092 if (!(token instanceof ServiceRecord)) {
14093 throw new IllegalArgumentException("Invalid service token");
14094 }
14095 mServices.publishServiceLocked((ServiceRecord)token, intent, service);
14096 }
14097 }
在publishService中又调用了ActivityServices的publishServiceLocked方法。
//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
1836 void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
1837 final long origId = Binder.clearCallingIdentity();
1838 try {
1839 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "PUBLISHING " + r
1840 + " " + intent + ": " + service);
1841 if (r != null) {
1842 Intent.FilterComparison filter
1843 = new Intent.FilterComparison(intent);
1844 IntentBindRecord b = r.bindings.get(filter);
1845 if (b != null && !b.received) {
1846 b.binder = service;
1847 b.requested = true;
1848 b.received = true;
1849 ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
1850 for (int conni = connections.size() - 1; conni >= 0; conni--) {
1851 ArrayList<ConnectionRecord> clist = connections.valueAt(conni);
1852 for (int i=0; i<clist.size(); i++) {
1853 ConnectionRecord c = clist.get(i);
1854 if (!filter.equals(c.binding.intent.intent)) {
1855 if (DEBUG_SERVICE) Slog.v(
1856 TAG_SERVICE, "Not publishing to: " + c);
1857 if (DEBUG_SERVICE) Slog.v(
1858 TAG_SERVICE, "Bound intent: " + c.binding.intent.intent);
1859 if (DEBUG_SERVICE) Slog.v(
1860 TAG_SERVICE, "Published intent: " + intent);
1861 continue;
1862 }
1863 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c);
1864 try {//调用ServiceDispatcher.InnerConnection的connected方法
1865 c.conn.connected(r.name, service, false);
1866 } catch (Exception e) {
1867 Slog.w(TAG, "Failure sending service " + r.shortInstanceName
1868 + " to connection " + c.conn.asBinder()
1869 + " (in " + c.binding.client.processName + ")", e);
1870 }
1871 }
1872 }
1873 }
1874
1875 serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
1876 }
1877 } finally {
1878 Binder.restoreCallingIdentity(origId);
1879 }
1880 }
c.conn会调用ServiceDispatcher.InnerConnection的connected方法。
//frameworks/base/core/java/android/app/LoadedApk.java
1756 static final class ServiceDispatcher {
1757 private final ServiceDispatcher.InnerConnection mIServiceConnection;
1758 @UnsupportedAppUsage
1759 private final ServiceConnection mConnection;
1760 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
1761 private final Context mContext;
1762 private final Handler mActivityThread;
1763 private final Executor mActivityExecutor;
1764 private final ServiceConnectionLeaked mLocation;
1765 private final int mFlags;
1766
1767 private RuntimeException mUnbindLocation;
1768
1769 private boolean mForgotten;
1770
1771 private static class ConnectionInfo {
1772 IBinder binder;
1773 IBinder.DeathRecipient deathMonitor;
1774 }
1775
1776 private static class InnerConnection extends IServiceConnection.Stub {
1777 @UnsupportedAppUsage
1778 final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
1779
1780 InnerConnection(LoadedApk.ServiceDispatcher sd) {
1781 mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
1782 }
1783
1784 public void connected(ComponentName name, IBinder service, boolean dead)
1785 throws RemoteException {
1786 LoadedApk.ServiceDispatcher sd = mDispatcher.get();
1787 if (sd != null) {//调用ServiceDispatcher类型的sd对象的connected
1788 sd.connected(name, service, dead);
1789 }
1790 }
1791 }1878 public void connected(ComponentName name, IBinder service, boolean dead) {
1879 if (mActivityExecutor != null) {
1880 mActivityExecutor.execute(new RunConnection(name, service, 0, dead));
1881 } else if (mActivityThread != null) {//将RunConnection对象的内容运行在主线程中
1882 mActivityThread.post(new RunConnection(name, service, 0, dead));
1883 } else {
1884 doConnected(name, service, dead);
1885 }
1886 }
//frameworks/base/core/java/android/app/LoadedApk.java
1970 private final class RunConnection implements Runnable {
1971 RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
1972 mName = name;
1973 mService = service;
1974 mCommand = command;
1975 mDead = dead;
1976 }
1977
1978 public void run() {
1979 if (mCommand == 0) {//调用doConnected方法
1980 doConnected(mName, mService, mDead);
1981 } else if (mCommand == 1) {
1982 doDeath(mName, mService);
1983 }
1984 }
1985
1986 final ComponentName mName;
1987 final IBinder mService;
1988 final int mCommand;
1989 final boolean mDead;
1990 }1898 public void doConnected(ComponentName name, IBinder service, boolean dead) {
1899 ServiceDispatcher.ConnectionInfo old;
1900 ServiceDispatcher.ConnectionInfo info;
1901
1902 synchronized (this) {
1903 if (mForgotten) {
1904 // We unbound before receiving the connection; ignore
1905 // any connection received.
1906 return;
1907 }
1908 old = mActiveConnections.get(name);
1909 if (old != null && old.binder == service) {
1910 // Huh, already have this one. Oh well!
1911 return;
1912 }
1913
1914 if (service != null) {
1915 // A new service is being connected... set it all up.
1916 info = new ConnectionInfo();
1917 info.binder = service;
1918 info.deathMonitor = new DeathMonitor(name, service);
1919 try {
1920 service.linkToDeath(info.deathMonitor, 0);
1921 mActiveConnections.put(name, info);
1922 } catch (RemoteException e) {
1923 // This service was dead before we got it... just
1924 // don't do anything with it.
1925 mActiveConnections.remove(name);
1926 return;
1927 }
1928
1929 } else {
1930 // The named service is being disconnected... clean up.
1931 mActiveConnections.remove(name);
1932 }
1933
1934 if (old != null) {
1935 old.binder.unlinkToDeath(old.deathMonitor, 0);
1936 }
1937 }
1938
1939 // If there was an old service, it is now disconnected.
1940 if (old != null) {
1941 mConnection.onServiceDisconnected(name);
1942 }
1943 if (dead) {
1944 mConnection.onBindingDied(name);
1945 }
1946 // If there is a new viable service, it is now connected.
1947 if (service != null) {//调用ServiceConnection的onServiceConnected方法
1948 mConnection.onServiceConnected(name, service);
1949 } else {
1950 // The binding machinery worked, but the remote returned null from onBind().
1951 mConnection.onNullBinding(name);
1952 }
1953 }
我们最后调用了调用ServiceConnection的onServiceConnected方法,这样在客户端实现了ServiceConnection的onServiceConnected方法就会被执行,至此Service的绑定过程全部结束。
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- OpenGL学习笔记(六)
着色器程序简介使用 简介 着色器程序对象(Shader Program Object)是多个着色器合并之后并最终链接完成的版本。使用着色器前,必须先把它们链接(Link)为一个着色器程序对象,然后在渲染对象的时候激活这个着色器程序,已激活着色器程序的着色器将在发送渲染调用的时候被使用。 …...
2024/4/24 9:31:24 - iOS开发-OC、Swift、C、C++ 混合编程
OC、Swift、C、C++可以互相调用,也可以混合编程,只需要注意一些规则和配置即可。1、IOS Xcode文件中m,mm,cpp,h后缀名的区别.h:头文件。头文件包含类,类型,函数和常数的声明。.m:源代码文件。这是典型的源代码文件扩展名,可以包含Objective-C和C代码。.mm:源代码文件。…...
2024/4/24 9:31:23 - 顶级管理思维-金字塔顶端的俯视
你在山脚下的时候,一切都是那么的大。好像每走一步都很艰难。但是如果你在金字塔顶端的时候。一切都那么渺小。你会看到所有的人正在向这个金字塔顶在爬,站在顶端的你。你可以看到所有人速度,哪个快哪个慢,金字塔顶是很小的。他很容易摔下去。因为他就这么小。看到下面这个…...
2024/4/24 9:31:22 - 第二章-intellij IDEA的安装和基本配置
IDEA的项目结构根据软件引导可以创建项目及下属模块,创建完成后可在左侧看到项目的相关文件,src文件夹包含项目中的所有源代码,iml文件则是IDEA的相关配置信息,External Libraries存放JDK 根据需要在src文件夹内点击右键创建包,创建格式一般使用英文小写,数字,英文句点等…...
2024/4/24 9:31:24 - css position定位的使用
css position定位的使用图里面的坐标p1,如果没有position属性,即使设置了坐标也是不生效的。 p1的定位是相对于父元素的,父元素一定要有position的属性才能生效。...
2024/4/24 9:31:23 - IC设计高级005:自恢复设计
1、什么是自恢复设计?在芯片设计过程中,通常会针对特殊情况导致芯片无法使用额外添加一些功能,使得芯片具有更好的抗干扰能力。自恢复设计应用场景很广泛,比如、针对芯片温度过高的处理、针对残缺数据包的处理、针对长时间无数据响应的处理、针对各类错误的处理2、常见的自…...
2024/4/24 9:31:21 - 微信公众号如何关联小程序?如何查看小程序原始ID?
传送门: 公众号认证?小程序认证?小程序复用公众号资质进行认证? https://blog.csdn.net/pang787559613/article/details/106455907 小程序被冻结,忘记原始iD,如何找回? https://blog.csdn.net/pang787559613/article/details/106456041一、公众号关联小程序: 登录公众号…...
2024/4/26 0:44:59 - NO.5 ROS Turtle &日志开发
零蚀小乌龟小乌龟的消息在这里小乌龟既有接收方的cmd - topicName,也有发送方,这里的/turtle/pose里面就是设置小乌龟在运动时候发出的数据信息,我们通过pose这个信息科技做一个观察者,来接受数据。查看小乌龟发送的数据类型是turtlesim/Pose#include "turtlesim/Pose.…...
2024/4/19 21:50:55 - Git学习--常见常用命令
本人也是自学Git,为了方便自己后期学习,也为让大家一起学习。特此,写下本片博客。若有问题还请前辈们指出,本片博客,为自己边学边记录。 Git下载 Git下载(官网地址 ):https://git-scm.com/download/win 官网下载速度比较慢,我这提供一个我于2020.5.24日开始学习下载的…...
2024/4/20 14:13:49 - 1.3.2时序图分析示例
以Nor Flash为例,分析一下2440和Nor Flash的通信时序。Nor Flash的电路图如上所示,与2440的大致连接如下图所示,有地址线Addr,数据线Data,片选信号nCS,读使能nOE,写使能nWE。以2440芯片手册提供的读时序图为例,分析一下2440从存储芯片中读数据的时序。从左到右分析时序…...
2024/4/16 10:52:49 - 第二篇:FFmpeg基本指令
02.简介,上手(FFmpeg FFprobe FFplay) (1)查看ffmpeg的帮助说明,提供的指令 ffmpeg -h (2)播放媒体的指令 ffplay video.mp4 ffplay music.mp3 (3)常用快捷键 按键"Q"或"Esc":退出媒体播放 键盘方向键:媒体播放的前进后退 点击鼠标右键:拖动到该播放位…...
2024/4/24 9:31:21 - 深度分析:高并发系统架构设计原理,史上最全系列!
架构设计是一系列相关的抽象模式,是人们对一个结构内的元素及元素间关系的一种主观映射的产物。一、计算机网络基础 A. OSI模型 OSI Open System Interconnection,简称OSI模型或七层模型。 开放系统互连参考模型,是国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)联…...
2024/4/24 9:31:17 - Js查漏补缺-09
0x00 事件流removeElementListener();可以解除元素的事件监听器绑定事件流是页面中接受事件的传递顺序,包括捕获阶段,当前目标阶段,冒泡阶段注意,Js只能执行冒泡或者捕获中的一个阶段;onclick等注册事件以及attachEvent只能得到冒泡阶段;addEventListener()若第三个参数…...
2024/4/24 9:31:19 - Envoy 测试笔记
Envoy 测试笔记envoy 提供的官方镜像:envoyproxy/envoy envoyproxy/envoy-alpine镜像配置文件 /etc/envoy/envoy.yaml 默认监听 端口:10000 // 测试命令docker run -d --name envoy-test -p 10000:10000 \ -v /home/zhangfeng/envoy/conf:/etc/envoy/ \ envoyproxy/envoydoc…...
2024/4/24 9:31:15 - 为什么如此年轻
一次采访中,金星问许晴:“50岁了还不结婚,你想要什么样的男人?” 许晴一脸笑意,温柔地说道:“其实,我要的男人就是要深情,我要的爱情就是神韵,” 金星有些不相信,问道:“神韵?”“一般很多女人对男人要事业有成,各方面都要很好,而你对男人的要求是每次打电话,就…...
2024/4/24 9:31:17 - 五层网络
一、应用层 应用层是网络应用程序及其应用层协议存留的地方。 应用层包含许多协议,例如HTTP(它为web文档提供了请求和传送)、SMTP(它提供了电子邮件报文的传输)和FTP(它提供了两个端系统之间的文件传送)。 二、运输层 负责为信源和信宿提供应用程序进程间的数据传输服务,这一…...
2024/4/24 9:31:14 - 网络营销为传统零售企业增效
网络营销如何才能更好地在传统零售企业中发挥更大的作用。网络营销给传统零售业带来了更大的发展空间,但如何发展目前并没有合适的模式。 据统计,目前在美国开展B2C网络营销的企业中,70% 来自于传统零售企业。中国连锁业经营协会公布的2004年中国连锁百强企业中,70%的企业建…...
2024/4/24 9:31:12 - 表示数值的字符串【转载】
文章目录1 问题2 解题思路3 代码实现 1 问题请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、"5e2"、"-123"、"3.1416"、"0123"都表示数值,但"12e"、"1a3.14"、&qu…...
2024/4/24 9:31:11 - Sharding-JDBC实现读写分离
一、前言二 、windos下mysql主从复制环境准备初始化数据库配置my.ini三、与Spring结合前言Sharding-JDBC实现读写分离,参考黑马程序员的视频,再结合4.x的官网介绍,视频中未解决分布式事务,在现版本已有解决方案。这种透明化的处理,配置好数据库分库分表规则就可以使用,真…...
2024/4/24 9:31:10 - 最全 AndroidStudio 快捷键及使用技巧(git图)
写在前面本文翻译自 Android Studio Tips by Philippe Breault,一共收集了62个 Android Studio 使用小技巧和快捷键。 根据这些小技巧的使用场景,本文将这62个小技巧分为常用技巧(1 – 28)、编码技巧(29 – 49)和调试技巧(50 – 62),分成三个部分。每个小技巧都配有 g…...
2024/4/24 9:31:09
最新文章
- JavaFX 动态加载目录下所有WAV文件并逐个播放
在JavaFX中动态加载一个目录下的所有.wav文件并逐个播放,你可以使用java.nio.file包来遍历目录,并使用javax.sound.sampled包来播放音频文件。不过,需要注意的是,JavaFX本身并不直接支持音频播放,但你可以使用Java的标…...
2024/5/4 1:01:16 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/3/20 10:50:27 - 腾讯云轻量服务器流量不够用了会怎么样?
腾讯云轻量应用服务器是限制月流量的,如果当月流量不够用了,流量超额了怎么办?流量超额后,需要另外支付流量费,如果你的腾讯云账号余额,就会自动扣除对应的流量费,如果余额不足,轻量…...
2024/5/1 13:01:36 - CSS3 高级- 复杂选择器、内容生成、变形(transform)、过渡(transition)、动画(animation)
文章目录 一、复杂选择器兄弟选择器:选择平级元素的唯一办法属性选择器:1、通用:基本用不着,太泛了2、自定义:4种伪类选择器:1、目标伪类:2、结构伪类:3、元素状态伪类:4、伪元素选择器:应用于文字,使网页看起来想杂志5、否定伪类:选择器:not([本选择器的条件]) /*…...
2024/5/3 10:26:16 - 【外汇早评】美通胀数据走低,美元调整
原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...
2024/5/1 17:30:59 - 【原油贵金属周评】原油多头拥挤,价格调整
原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...
2024/5/2 16:16:39 - 【外汇周评】靓丽非农不及疲软通胀影响
原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...
2024/4/29 2:29:43 - 【原油贵金属早评】库存继续增加,油价收跌
原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...
2024/5/3 23:10:03 - 【外汇早评】日本央行会议纪要不改日元强势
原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...
2024/4/27 17:58:04 - 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响
原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...
2024/4/27 14:22:49 - 【外汇早评】美欲与伊朗重谈协议
原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...
2024/4/28 1:28:33 - 【原油贵金属早评】波动率飙升,市场情绪动荡
原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...
2024/4/30 9:43:09 - 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试
原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...
2024/4/27 17:59:30 - 【原油贵金属早评】市场情绪继续恶化,黄金上破
原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...
2024/5/2 15:04:34 - 【外汇早评】美伊僵持,风险情绪继续升温
原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...
2024/4/28 1:34:08 - 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势
原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...
2024/4/26 19:03:37 - 氧生福地 玩美北湖(上)——为时光守候两千年
原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...
2024/4/29 20:46:55 - 氧生福地 玩美北湖(中)——永春梯田里的美与鲜
原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...
2024/4/30 22:21:04 - 氧生福地 玩美北湖(下)——奔跑吧骚年!
原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...
2024/5/1 4:32:01 - 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!
原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...
2024/4/27 23:24:42 - 「发现」铁皮石斛仙草之神奇功效用于医用面膜
原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...
2024/4/28 5:48:52 - 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者
原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...
2024/4/30 9:42:22 - 广州械字号面膜生产厂家OEM/ODM4项须知!
原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...
2024/5/2 9:07:46 - 械字号医用眼膜缓解用眼过度到底有无作用?
原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...
2024/4/30 9:42:49 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57